commit 7d08a2ffefa6b353fdceba059f0a8965562d71dd Author: Lephenixnoir Date: Fri Jun 18 11:48:50 2021 +0200 initial-with-some-changes diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c4f84b --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Build files +/build-fx +/build-cg +/*.g1a +/*.g3a + +# Python bytecode + __pycache__/ + +# Common IDE files +*.sublime-project +*.sublime-workspace +.vscode diff --git a/CMakeLists - Kikoudx.txt b/CMakeLists - Kikoudx.txt new file mode 100644 index 0000000..2bfe772 --- /dev/null +++ b/CMakeLists - Kikoudx.txt @@ -0,0 +1,86 @@ +# Configure with [fxsdk build-fx] or [fxsdk build-cg], which provide the + # toolchain file and module path of the fxSDK + + cmake_minimum_required(VERSION 3.18) + # replace this with your project's name + project(Windmill) + + include(GenerateG1A) + include(GenerateG3A) + include(Fxconv) + find_package(Gint 2.1 REQUIRED) + + # include directories, put your .h files in those folders + include_directories(include) + + # source files + set(SOURCES + src/main.cpp + + # ... + ) + # shared assets + set(ASSETS + # ... + ) + # fx-9860G-only assets (monochrome) + set(ASSETS_fx + assets-fx/example.png + assets-fx/img/windmill.png + # ... + ) + # fx-CG-50-only assets (polychrome) + set(ASSETS_cg + assets-cg/example.png + # ... + ) + + # Compile flags + set(FLAGS + # C standard, other values: c89, c99 + -std=c11 + + # general warnings + -Wall -Wextra -pedantic + + # enable this flag to stop compilation on warnings + #-Werror + + # specific warnings + # variable shadowing + -Wshadow + # switch/case safety + -Wswitch-default -Wswitch-enum + # unreachable code, bad 99% of the time + -Wunreachable-code + # prototypes warnings + -Wstrict-prototypes -Wmissing-prototypes + # function declaration + -Werror-implicit-function-declaration + + # optimisation level + # -Os: like -O2 without space-expensive optimizations + # -O2: good speed/size tradeoff + # -O3: gotta go fast + -Os + ) + + fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA) + + add_executable(${PROJECT_NAME} ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}}) + target_compile_options(${PROJECT_NAME} PRIVATE ${FLAGS}) + target_link_libraries(${PROJECT_NAME} Gint::Gint) + + if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) + generate_g1a( + TARGET ${PROJECT_NAME} + OUTPUT "${PROJECT_NAME}.g1a" + NAME "${PROJECT_NAME}" + ICON assets-fx/icon.png) + elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) + generate_g3a( + TARGET ${PROJECT_NAME} + OUTPUT "${PROJECT_NAME}.g3a" + NAME "${PROJECT_NAME}" + ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) + endif() \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2308fd5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,61 @@ +# Configure with [fxsdk build-fx] or [fxsdk build-cg], which provide the +# toolchain file and module path of the fxSDK + +cmake_minimum_required(VERSION 3.18) +project(Windmill) + +include(GenerateG1A) +include(GenerateG3A) +include(Fxconv) +find_package(Gint 2.1 REQUIRED) + +set(SOURCES + src/main.cpp + src/windmill.cpp + src/map.cpp + src/scene_map.cpp + src/camera.cpp + src/game.cpp + src/player.cpp + # ... +) +# Shared assets, fx-9860G-only assets and fx-CG-50-only assets +set(ASSETS + # ... +) +set(ASSETS_fx + assets-fx/example.png + assets-fx/img/windmill.png + # ... +) +set(ASSETS_cg + assets-cg/example.png + # ... +) + +fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA) + +set_source_files_properties(src/map.cpp PROPERTIES + COMPILE_OPTIONS "-Wp,-w;-Wno-missing-field-initializers") + +add_executable(${PROJECT_NAME} ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}}) + +target_include_directories(${PROJECT_NAME} PRIVATE "${FXSDK_COMPILER_INSTALL}/include/openlibm") + +target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Os -fno-use-cxa-atexit) + +target_link_libraries(${PROJECT_NAME} Gint::Gint -lopenlibm -lc -lsupc++) + +if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) + generate_g1a( + TARGET ${PROJECT_NAME} + OUTPUT "${PROJECT_NAME}.g1a" + NAME "${PROJECT_NAME}" + ICON assets-fx/icon.png) + elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) + generate_g3a( + TARGET ${PROJECT_NAME} + OUTPUT "${PROJECT_NAME}.g3a" + NAME "${PROJECT_NAME}" + ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png) + endif() diff --git a/LEPHE.md b/LEPHE.md new file mode 100644 index 0000000..1a4fb4e --- /dev/null +++ b/LEPHE.md @@ -0,0 +1,45 @@ +Changements faits par Lephe' pour que ça compile : + +## Dans CMakeLists.txt + +* Ajouté `-Wp,-w` à src/map.cpp ; ça indique à GCC de passer `-w` au préprocesseur, ce qui désactive (entre autres) les avertissements de redéfinition de macros pour ce fichier (normalement il faut `#undef` les macros avant de les redéfinir). + +Pour information: `-W,` passe les options (séparées par des virgules) au programme spécifié par la lettre dans la chaîne de compilation : `-Wp` passe des options au préprocesseur, `-Wa` à l'assembleur, et `-Wl` à l'éditeur de liens. + +* Ajouté `-Wno-missing-field-initializers` à src/map.cpp, ce qui désactive les avertissements pour les champs non initialisés dans les structures ; attention du coup, si tu en oublies des importants personne ne te le dira. + +## Dans src/map.cpp et src/windmill.cpp + +* Rendu les textures (`tex_white`, `tex_black`, etc) non-constantes + - Dans src/map.cpp: `Texture tex_white = {};` + - Dans src/windmill.cpp `extern Texture tex_white;` + +C'est parce qu'en C++ `const` implique *internal linkage* (comme `static`), et du coup la variable n'est visible que dans le fichier où elle est déclarée. Du coup `extern const` c'est un peu bizarre, et même si certains bouts m'échappent, le résultat c'est que ça ne marche pas. Il y a probablement une meilleure solution que de couper le `const`, à rechercher une autre fois. + +En déclarant les textures non-constantes les noms sont exportés comme il faut et se retrouvent bien. Du coup les 4 textures arrivent dans la section `.bss` (RAM initialisée à 0) au lieu de `.rodata` (ROM) ; si c'est un problème et à défaut d'une autre solution, tu peux mettre `GSECTION(".rodata")` (de ``) devant le `Texture` et ça les déplacera dans leur section d'origine. + +## Dans src/windmill.cpp + +* Décommenté la vieille fonction `render_triangle_white`. J'ai vu que `render_triangle_black` avait été redéfinie, celle-là je n'y ai pas touché. + +## Test + +À ce stade ça compile et le programme ne crashe pas ; l'écran titre a juste une image de titre, et ensuite quand j'appuie sur EXE, écran noir. Pas moyen de sortir, je RESET. Manifestement c'est normal vu la tête de src/main.cpp. + +## Dans src/windmill.cpp and src/windmill.hpp + +* Décommenté tout le code concernant la VRAM ; la VRAM est accessible par la variable `gint_vram` déclarée dans ``. Sur Graph mono ce n'est pas un tableau de char mais un tableau de `uint32_t` donc attention ! Quand tu écris `char *vram = ...` ça ne pose pas de problème, mais `gint_vram[i]` contrôle 32 pixels d'un coup. + +* Dans src/windmill.hpp, ajouté `#define get_vram_address() ((char *)gint_vram)`. + +* Dans `draw_ground()`, renommé `sol.x` et `sol.y` en `ground.x` et `ground.y` dans la ligne suivante. + +```c +vram[(ground.y << 4) + (ground.x>>3)] |= mask; +``` + +## Test + +Pareil. + + diff --git a/assets-cg/example.png b/assets-cg/example.png new file mode 100644 index 0000000..8826800 Binary files /dev/null and b/assets-cg/example.png differ diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt new file mode 100644 index 0000000..d435d5f --- /dev/null +++ b/assets-cg/fxconv-metadata.txt @@ -0,0 +1,3 @@ +example.png: + type: bopti-image + name: img_example diff --git a/assets-cg/icon-sel.png b/assets-cg/icon-sel.png new file mode 100644 index 0000000..7137b50 Binary files /dev/null and b/assets-cg/icon-sel.png differ diff --git a/assets-cg/icon-uns.png b/assets-cg/icon-uns.png new file mode 100644 index 0000000..3c99f62 Binary files /dev/null and b/assets-cg/icon-uns.png differ diff --git a/assets-fx/.DS_Store b/assets-fx/.DS_Store new file mode 100644 index 0000000..14e5079 Binary files /dev/null and b/assets-fx/.DS_Store differ diff --git a/assets-fx/example.png b/assets-fx/example.png new file mode 100644 index 0000000..b26ba9a Binary files /dev/null and b/assets-fx/example.png differ diff --git a/assets-fx/fxconv-metadata.txt b/assets-fx/fxconv-metadata.txt new file mode 100644 index 0000000..13e15bb --- /dev/null +++ b/assets-fx/fxconv-metadata.txt @@ -0,0 +1,7 @@ +example.png: + type: bopti-image + name: img_example + +img/windmill.png: + type: bopti-image + name: img_windmill \ No newline at end of file diff --git a/assets-fx/icon.png b/assets-fx/icon.png new file mode 100644 index 0000000..b80992b Binary files /dev/null and b/assets-fx/icon.png differ diff --git a/assets-fx/img/.DS_Store b/assets-fx/img/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/assets-fx/img/.DS_Store differ diff --git a/assets-fx/img/brique base.png b/assets-fx/img/brique base.png new file mode 100644 index 0000000..d18a260 Binary files /dev/null and b/assets-fx/img/brique base.png differ diff --git a/assets-fx/img/brique.png b/assets-fx/img/brique.png new file mode 100644 index 0000000..5c7e594 Binary files /dev/null and b/assets-fx/img/brique.png differ diff --git a/assets-fx/img/epouvantail masque.png b/assets-fx/img/epouvantail masque.png new file mode 100644 index 0000000..79b01f3 Binary files /dev/null and b/assets-fx/img/epouvantail masque.png differ diff --git a/assets-fx/img/epouvantail.png b/assets-fx/img/epouvantail.png new file mode 100644 index 0000000..7877be3 Binary files /dev/null and b/assets-fx/img/epouvantail.png differ diff --git a/assets-fx/img/fenetre simple.png b/assets-fx/img/fenetre simple.png new file mode 100644 index 0000000..59c6900 Binary files /dev/null and b/assets-fx/img/fenetre simple.png differ diff --git a/assets-fx/img/forgeron.png b/assets-fx/img/forgeron.png new file mode 100644 index 0000000..b6ddf48 Binary files /dev/null and b/assets-fx/img/forgeron.png differ diff --git a/assets-fx/img/fxconv-metadata.txt b/assets-fx/img/fxconv-metadata.txt new file mode 100644 index 0000000..55fe97a --- /dev/null +++ b/assets-fx/img/fxconv-metadata.txt @@ -0,0 +1,3 @@ +windmill.png: + type: bopti-image + name: img_windmill \ No newline at end of file diff --git a/assets-fx/img/haie.png b/assets-fx/img/haie.png new file mode 100644 index 0000000..d0ec3b9 Binary files /dev/null and b/assets-fx/img/haie.png differ diff --git a/assets-fx/img/herbe.png b/assets-fx/img/herbe.png new file mode 100644 index 0000000..cb8156b Binary files /dev/null and b/assets-fx/img/herbe.png differ diff --git a/assets-fx/img/horloge.png b/assets-fx/img/horloge.png new file mode 100644 index 0000000..024af58 Binary files /dev/null and b/assets-fx/img/horloge.png differ diff --git a/assets-fx/img/mask_forgeron.png b/assets-fx/img/mask_forgeron.png new file mode 100644 index 0000000..58e2d03 Binary files /dev/null and b/assets-fx/img/mask_forgeron.png differ diff --git a/assets-fx/img/moulin mur.png b/assets-fx/img/moulin mur.png new file mode 100644 index 0000000..0b265b3 Binary files /dev/null and b/assets-fx/img/moulin mur.png differ diff --git a/assets-fx/img/moulin pale.png b/assets-fx/img/moulin pale.png new file mode 100644 index 0000000..f70cc5d Binary files /dev/null and b/assets-fx/img/moulin pale.png differ diff --git a/assets-fx/img/mur_int_maison.png b/assets-fx/img/mur_int_maison.png new file mode 100644 index 0000000..cd48ba5 Binary files /dev/null and b/assets-fx/img/mur_int_maison.png differ diff --git a/assets-fx/img/paille dessus.png b/assets-fx/img/paille dessus.png new file mode 100644 index 0000000..0e5c4f0 Binary files /dev/null and b/assets-fx/img/paille dessus.png differ diff --git a/assets-fx/img/paille.png b/assets-fx/img/paille.png new file mode 100644 index 0000000..d729d00 Binary files /dev/null and b/assets-fx/img/paille.png differ diff --git a/assets-fx/img/panneau.png b/assets-fx/img/panneau.png new file mode 100644 index 0000000..3d3b639 Binary files /dev/null and b/assets-fx/img/panneau.png differ diff --git a/assets-fx/img/pierre eglise.png b/assets-fx/img/pierre eglise.png new file mode 100644 index 0000000..d5ea934 Binary files /dev/null and b/assets-fx/img/pierre eglise.png differ diff --git a/assets-fx/img/pierre eglise2.png b/assets-fx/img/pierre eglise2.png new file mode 100644 index 0000000..b9cdc16 Binary files /dev/null and b/assets-fx/img/pierre eglise2.png differ diff --git a/assets-fx/img/planche bois.png b/assets-fx/img/planche bois.png new file mode 100644 index 0000000..be3db7c Binary files /dev/null and b/assets-fx/img/planche bois.png differ diff --git a/assets-fx/img/porte eglise.png b/assets-fx/img/porte eglise.png new file mode 100644 index 0000000..1dd1403 Binary files /dev/null and b/assets-fx/img/porte eglise.png differ diff --git a/assets-fx/img/porte simple.png b/assets-fx/img/porte simple.png new file mode 100644 index 0000000..17709a4 Binary files /dev/null and b/assets-fx/img/porte simple.png differ diff --git a/assets-fx/img/table.png b/assets-fx/img/table.png new file mode 100644 index 0000000..9b66e1b Binary files /dev/null and b/assets-fx/img/table.png differ diff --git a/assets-fx/img/toit tuile.png b/assets-fx/img/toit tuile.png new file mode 100644 index 0000000..a4c97c8 Binary files /dev/null and b/assets-fx/img/toit tuile.png differ diff --git a/assets-fx/img/windmill.png b/assets-fx/img/windmill.png new file mode 100644 index 0000000..5806252 Binary files /dev/null and b/assets-fx/img/windmill.png differ diff --git a/assets-fx/img/windmill2.png b/assets-fx/img/windmill2.png new file mode 100644 index 0000000..9bcd559 Binary files /dev/null and b/assets-fx/img/windmill2.png differ diff --git a/src/Scene_Title.cpp b/src/Scene_Title.cpp new file mode 100644 index 0000000..7d7d578 --- /dev/null +++ b/src/Scene_Title.cpp @@ -0,0 +1,87 @@ +#include "Scene_Title.hpp" +//#include "Map.hpp" + + +extern Game game; +extern int scene; +extern Windmill windmill; + +extern Map map_menu; + + +//---------------------------------------------------------------------------------------------------- +// CONSTRUCTOR +//---------------------------------------------------------------------------------------------------- +Scene_Title::Scene_Title() +{ + // rien +} + + +//---------------------------------------------------------------------------------------------------- +// LAUNCH +//---------------------------------------------------------------------------------------------------- +void Scene_Title::launch() +{ + time_scene = 0; + + camera.set(-20, 110, 16, 301, 25); + windmill.load_map(&map_menu); + windmill.set_camera(&camera); +} + + +//---------------------------------------------------------------------------------------------------- +// UPDATE +//---------------------------------------------------------------------------------------------------- +void Scene_Title::update() +{ + time_scene += 0.02; + + map_menu.object[1]->angle += 1; + //camera.y = 40 * sinf(2*PI * time_scene / 10); + //camera.set_yaw(20 - 10 * sinf(2*PI * time_scene / 10)); + + if (time_scene > 0.2 and input_trigger(K_SHIFT)) + { + scene = SCENE_MAP; + } +} + + +//---------------------------------------------------------------------------------------------------- +// DRAW +//---------------------------------------------------------------------------------------------------- +void Scene_Title::draw() +{ + ML_clear_vram(); + + windmill.draw(); + + ML_bmp_and(sprite_titre_windmill2, 16, 0, 96, 21); + ML_bmp_or(sprite_titre_windmill, 16, 0, 96, 21); + + if (int(2*time_scene) % 2 == 0) + { + PrintMini(25, 58, "Appuyer sur [shift]", MINI_OVER); + } + + ML_display_vram(); +} + + +//---------------------------------------------------------------------------------------------------- +// TERMINATE +//---------------------------------------------------------------------------------------------------- +void Scene_Title::terminate() +{ + +} + +//---------------------------------------------------------------------------------------------------- +// DESTRUCTOR +//---------------------------------------------------------------------------------------------------- +Scene_Title::~Scene_Title() +{ + // rien +} \ No newline at end of file diff --git a/src/Scene_Title.hpp b/src/Scene_Title.hpp new file mode 100644 index 0000000..74caa04 --- /dev/null +++ b/src/Scene_Title.hpp @@ -0,0 +1,122 @@ +//---------------------------------------------------------------------------------------------------- +// +// WINDMILL v1.0 +// +// Scene_Title.hpp +// +//---------------------------------------------------------------------------------------------------- + +#ifndef DEF_SCENE_TITLE +#define DEF_SCENE_TITLE + + +extern "C" +{ + #include "Input.h" +} +#include "Game.hpp" +#include "Windmill.hpp" +#include "Camera.hpp" +#include "MonochromeLib.h" +#include "Debug.hpp" + + +#define EXIT 0 +#define SCENE_TITLE 1 +#define SCENE_MAP 2 +#define SCENE_MAP_DEBUG 3 + +#define PI 3.1415 + + +const unsigned char sprite_titre_windmill[]={ + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1c,0x70, + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x1c,0x70, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x38,0xe0, + 0x0f,0x80,0x03,0x80,0x00,0x00,0x0e,0x00,0x00,0x00,0x38,0xe0, + 0x03,0x81,0x83,0x98,0x00,0x00,0x0c,0x00,0x00,0x0c,0x30,0xc0, + 0x03,0x83,0x83,0x38,0x00,0x00,0x1c,0x00,0x00,0x1c,0x71,0xc0, + 0x03,0x87,0x87,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x61,0x80, + 0x03,0x87,0x06,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xe3,0x80, + 0x03,0x8f,0x0c,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xc3,0x00, + 0x03,0x9b,0x18,0x63,0x9e,0x03,0xf1,0xce,0x78,0x30,0xc3,0x00, + 0x03,0x1f,0x18,0xe1,0xb6,0x0e,0x30,0xff,0xd8,0x71,0xc7,0x00, + 0x03,0x37,0x30,0xc3,0xee,0x1c,0x61,0xe7,0x98,0x61,0x86,0x00, + 0x03,0x67,0x61,0xc3,0xcc,0x38,0xe1,0xef,0x38,0xe3,0x8e,0x00, + 0x07,0xc7,0xc1,0xc3,0x8c,0x71,0xe1,0xce,0x30,0xe3,0x8e,0x00, + 0x07,0xc7,0xc1,0x87,0x1c,0x73,0xc3,0x8e,0x70,0xc3,0x0c,0x00, + 0x07,0x87,0x83,0x86,0x18,0x66,0xc3,0x1c,0x61,0xc7,0x1c,0x00, + 0x07,0x07,0x03,0x8e,0x38,0x6d,0xc7,0x18,0x61,0xc7,0x1c,0x00, + 0x06,0x0e,0x03,0xcc,0x3c,0x79,0xe6,0x38,0xf1,0xe7,0x9e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00, +}; + +const unsigned char sprite_titre_windmill2[]={ + 0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x7f,0xff,0xff,0xc1,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xc1,0x00, + 0xe0,0x3f,0xfc,0x3f,0xff,0xff,0xf0,0xff,0xff,0xff,0x80,0x00, + 0xe0,0x3e,0x3c,0x3f,0xff,0xff,0xe0,0xff,0xff,0xf1,0x82,0x00, + 0xe0,0x3c,0x38,0x27,0xff,0xff,0xe0,0xff,0xff,0xe1,0x86,0x10, + 0xf8,0x38,0x38,0x07,0xff,0xff,0xc1,0xff,0xff,0xc1,0x84,0x10, + 0xf8,0x38,0x30,0xff,0xff,0xff,0xc3,0xff,0xff,0xc1,0x0c,0x30, + 0xf8,0x30,0x21,0x0f,0xff,0xff,0x03,0xff,0xff,0xfe,0x08,0x30, + 0xf8,0x20,0x01,0x0c,0x20,0xf8,0x00,0x30,0x03,0x86,0x18,0x30, + 0xf8,0x00,0x02,0x0c,0x00,0xf0,0x04,0x00,0x03,0x86,0x18,0x70, + 0xf8,0x00,0x02,0x08,0x00,0xc0,0x06,0x00,0x03,0x86,0x30,0x70, + 0xf8,0x00,0x04,0x08,0x00,0x81,0x0e,0x00,0x03,0x04,0x30,0xf0, + 0xf0,0x00,0x0c,0x18,0x00,0x02,0x0c,0x00,0x02,0x0c,0x20,0xf0, + 0xf0,0x00,0x1c,0x10,0x01,0x04,0x1c,0x00,0x06,0x08,0x60,0xf0, + 0xf0,0x10,0x18,0x10,0x01,0x08,0x18,0x00,0x84,0x18,0x60,0xf0, + 0xf0,0x30,0x38,0x20,0x03,0x00,0x18,0x01,0x8c,0x10,0xc1,0xf0, + 0xf0,0x60,0x78,0x00,0x81,0x00,0x00,0x03,0x04,0x00,0x40,0xf0, + 0xf0,0xe0,0x78,0x01,0x81,0x00,0x00,0x82,0x04,0x00,0x00,0xf0, + 0xf1,0xe1,0xf8,0x01,0x81,0x00,0x00,0x86,0x04,0x00,0x00,0xf0, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf0, +}; + + + + +class Scene_Title +{ +public: + Scene_Title(); + void launch(); + void update(); + void draw(); + void terminate(); + ~Scene_Title(); + + Camera camera; + float time_scene; + + // perso + +}; + +#endif + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..df79065 --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,196 @@ +#include "camera.hpp" + +//----------------------------------------------------------------------------- +// CAMERA +//----------------------------------------------------------------------------- +Camera::Camera() +{ + x = 0; + y = 0; + z = 0; + yaw = 0; + pitch = 0; + fov = 50; + near = 1; + far = 1000; + + float fov_rad = to_rad(fov); + scale_coef = 64 * near * tanf(fov_rad); + cos_fov = SCALE_AI * cosf(fov_rad); + //sin_fov = SCALE_AI * sinf(fov_rad); + sin_fov = sinf(fov_rad); + cos_fov_square = cosf(fov_rad) * cosf(fov_rad); + //near_coef = - far / float(far - near); + //far_coef = - far * near * 128 / (far - near); + +} + + +//----------------------------------------------------------------------------- +// SET +//----------------------------------------------------------------------------- +void Camera::set(float _x, float _y, float _z, float _yaw, float _pitch) +{ + x = _x; + y = _y; + z = _z; + yaw = to_rad(_yaw); + pitch = to_rad(_pitch); +} + +void Camera::set(Camera* _camera) +{ + x = _camera->x; + y = _camera->y; + z = _camera->z; + yaw = _camera->yaw; + pitch = _camera->pitch; +} + +//----------------------------------------------------------------------------- +// UPDATE_CAMERA +//----------------------------------------------------------------------------- +void Camera::update() +{ + if (look_at_duration) + { + yaw = (yaw * (look_at_duration - 1) + look_at_yaw) / look_at_duration; + look_at_duration -= 1; + } + + cos_yaw = cosf(yaw); + sin_yaw = sinf(yaw); + cos_pitch = cosf(pitch); + sin_pitch = sinf(pitch); + + //nx = SCALE_AI * cos_pitch * cos_yaw; + //ny = SCALE_AI * cos_pitch * sin_yaw; + //nz = SCALE_AI * sin_pitch; + + nx = cos_pitch * cos_yaw; + ny = cos_pitch * sin_yaw; + nz = sin_pitch; + + // a1 a2 a3 + // a4 a5 a6 + // a7 a8 a9 + + a1 = SCALE_AI * cos_pitch * cos_yaw; + a2 = SCALE_AI * cos_pitch * sin_yaw; + a3 = SCALE_AI * sin_pitch; + a4 = SCALE_AI * -sin_yaw; + a5 = SCALE_AI * cos_yaw; + a6 = SCALE_AI * 0; + a7 = SCALE_AI * -sin_pitch * cos_yaw; + a8 = SCALE_AI * sin_pitch * -sin_yaw; + a9 = SCALE_AI * cos_pitch; +} + + +//----------------------------------------------------------------------------- +// NORMAL_VECTOR +//----------------------------------------------------------------------------- +void Camera::direction_vector(float* _x, float* _y) +{ + *_x = cos_yaw; + *_y = sin_yaw; +} + + +//----------------------------------------------------------------------------- +// MOVE_FRONT (valeur positive signifie devant) +//----------------------------------------------------------------------------- +void Camera::move_front(float value) +{ + x += value * cosf(yaw); + y -= value * sinf(yaw); +} + + +//----------------------------------------------------------------------------- +// MOVE_SIDE (valeur positive signifie à droite) +//----------------------------------------------------------------------------- +void Camera::move_side(float value) +{ + x -= value * sinf(yaw); + y -= value * cosf(yaw); +} + +//----------------------------------------------------------------------------- +// MOVE_ALTITUDE (valeur positive signifie en haut) +//----------------------------------------------------------------------------- +void Camera::move_altitude(float value) +{ + z += value; +} + + +//----------------------------------------------------------------------------- +// TURN_YAW (valeur positive signifie a gauche) +//----------------------------------------------------------------------------- +void Camera::turn_yaw(float value) +{ + yaw += to_rad(value); +} + +//----------------------------------------------------------------------------- +// TURN_PITCH (valeur positive signifie en haut) +//----------------------------------------------------------------------------- +void Camera::turn_pitch(float value) +{ + pitch += to_rad(value); +} + + +//----------------------------------------------------------------------------- +// SET_YAW (valeur positive signifie a gauche) +//----------------------------------------------------------------------------- +void Camera::set_yaw(float value) +{ + yaw = to_rad(value); +} + +//----------------------------------------------------------------------------- +// SET_PITCH (valeur positive signifie en haut) +//----------------------------------------------------------------------------- +void Camera::set_pitch(float value) +{ + pitch = to_rad(value); +} + + +//----------------------------------------------------------------------------- +// LOOK_AT +//----------------------------------------------------------------------------- +void Camera::look_at(float look_at_x, float look_at_y, float look_at_z, float duration) +{ + look_at_yaw = 0;//atan2f(look_at_y - y, look_at_x - x); + + //look_at_pitch = atan2(look_at_z - z, look_at_x - x); + // calcule de sqrt ?? + look_at_duration = duration; +} + +/* +//----------------------------------------------------------------------------- +// MIN +//----------------------------------------------------------------------------- +int Camera::min(int a, int b) +{ + return (a < b) ? a : b; +} + + +//----------------------------------------------------------------------------- +// MAX +//----------------------------------------------------------------------------- +int Camera::max(int a, int b) +{ + return (a > b) ? a : b; +} +*/ + + + + + diff --git a/src/camera.hpp b/src/camera.hpp new file mode 100644 index 0000000..d42a672 --- /dev/null +++ b/src/camera.hpp @@ -0,0 +1,123 @@ +//----------------------------------------------------------------------------- +// +// CAMERA +// +// Repere monde Repere camera : z rentre dans l'ecran +// z O------ x +// | y | +// |/ | +// ☐☐◁ O---- x y +// +// rotation autour de z de x vers y : rotation droite vers gauche : yaw +// rotation autour de y' de x' vers z' : rotation de bas vers haut : pitch +// +// avec yaw = pitch = 0, la camera regarde vers x, avec y à gauche et z en haut +// +// les objets sont affiches dans le sens trigo +// +// texture : O----->w +// | +// | +// h +// +// sens trigonométrique pour afficher la face avant +// le 0 texture correspond au 0 triangle et 0 rectangle +// +// triangle : 0-----2 avec offset 0-----2 +// | / de 50% c'est | | +// | / le point 1 | | +// | / qui se décale | | +// | / | +// 1 1 +// +// rectangle : 0-----2 +// | /| +// | / | +// | / | +// | / | +// 1-----3 3 est automatiquement crée +//----------------------------------------------------------------------------- + +#ifndef DEF_CAMERA +#define DEF_CAMERA + +extern "C" +{ + #define __BSD_VISIBLE 1 + #include + #include +} + + +//#define PI 3.1415 +#define DEG 180.0 +#define to_rad(x) M_PI / DEG * x +#define to_deg(x) DEG / M_PI * x +#define SCALE_AI 128 + + +class Camera +{ +public: + Camera(); + void set(float _x, float _y, float _z, float _yaw, float _pitch); + void set(Camera* _camera); + void update(); + + void direction_vector(float* _x, float* _y); + + //void move(float _x, float _y, float _z); + void move_front(float value); + void move_side(float value); + void move_altitude(float value); + + void turn_yaw(float value); + void turn_pitch(float value); + void set_yaw(float value); + void set_pitch(float value); + + void look_at(float _x, float _y, float _z, float duration); + + + void turn(float _yaw, float _pitch); + + //int min(int a, int b); + //int max(int a, int b); + +public: + + float x, y, z; + float yaw, pitch; + +public: + int look_at_type; + float look_at_yaw; + float look_at_pitch; + float look_at_duration; + + + //int nx, ny, nz; + float nx, ny, nz; + float cos_yaw, sin_yaw; + float cos_pitch, sin_pitch; + + float fov; + int cos_fov; + //int sin_fov; + float sin_fov; + float cos_fov_square; + + int scale_coef; + int near; + int far; + float near_coef; + int far_coef; + + float normal_x, normal_y, normal_z; + + int a1, a2, a3, a4, a5, a6, a7, a8, a9; +}; + + + +#endif diff --git a/src/game.cpp b/src/game.cpp new file mode 100644 index 0000000..941bf19 --- /dev/null +++ b/src/game.cpp @@ -0,0 +1,33 @@ +#include "game.hpp" + +//----------------------------------------------------------------------------- +// GAME +//----------------------------------------------------------------------------- +Game::Game() +{ + time_game = 0; +} + + +//----------------------------------------------------------------------------- +// NEW_GAME +//----------------------------------------------------------------------------- +void Game::new_game() +{ + // pour exemple + //map = &map_exemple; + //map = &map_interieur_forgeron; // ICI LAUNCH GAME + player.teleport(0,0,0,0,0); + //player.dissociate_camera = true; + //scene_map.camera.set(-14,25,5,90,0); // de face + //player.teleport(25,-50,0,90,0); + //scene_map.camera.set(-14,1,5,-20,0); // de biais + + //map = &map_village; + + //scene_map.load_map(); + //player.teleport(-85.7, -77.5, 0, 40, 0); + //player.teleport(0, -5, 0, 0, 0); + //player.teleport(250.7, -110.7, 0, 26.8, 15.4); // bug chevauchement clip depth + //player.teleport(250.7, -110.7, 0, 319.6, 53.55); +} diff --git a/src/game.hpp b/src/game.hpp new file mode 100644 index 0000000..a593e49 --- /dev/null +++ b/src/game.hpp @@ -0,0 +1,93 @@ +#ifndef DEF_GAME +#define DEF_GAME + + +extern "C" +{ + #define __BSD_VISIBLE 1 + #include + //#include "MonochromeLib.h" +} + +//#include "camera.hpp" + +//#include "Structures.hpp" +#include "windmill.hpp" + +//#include "Scene_Map.hpp" +//#include "Debug.hpp" +//#include "Toolbox.h" + + + +#define MAP_EXTERIOR_LIMIT 1000 +#define COL_NO 0 +#define COL_GROUND 1 +#define COL_WALL 2 +#define COL_ON 3 +#define COL_CARA 4 +#define COL_BOUND 5 + + + +class Player +{ +public: + Player(); + void teleport(float _x, float _y, float _z, float _yaw, float _pitch); + + float x, y, z, yaw, pitch; + + bool moving, jumping, turning; + + float height; + float total_height; + float belly; + + float action_distance; + + float translation_speed; + float rotation_speed; + float jump_speed; + + float translation_speed_max; + float translation_acceleration; + float rotation_speed_max; + float jump_speed_max; + + bool dissociate_camera; + bool can_move; +}; + + + + + +class Game +{ +public: + Game(); + + void new_game(); + + // bool player_close_to(float x, float y); + // bool player_close_to(Object* object); + // bool player_contact_with(Object* object); + + //Object* get_object(int id); + + //Collision_flag collision(float* new_x, float* new_y, float* new_z); + //bool CollisionDroiteSeg(Vecteur wall, Vecteur player); + + + Map *map; + Player player; + float time_game; + bool* switchs[100]; + float* variables[100]; + //float time_map; +}; + + + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..5345e67 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,39 @@ +#include "main.hpp" + + +Game game; +Windmill windmill; +Scene_Map scene_map; + +int main(void) +{ + + extern bopti_image_t img_windmill; + + dclear(C_WHITE); + dimage(16, 0, &img_windmill); + + int key = 0; + + while(key != KEY_EXE) + { + dupdate(); + + key = getkey().key; + } + + dclear(C_BLACK); + dupdate(); + + scene_map.launch(); + + while(1) + { + scene_map.draw(); + scene_map.update(); + } + scene_map.terminate(); + + getkey(); + return 1; +} diff --git a/src/main.hpp b/src/main.hpp new file mode 100644 index 0000000..04bdadd --- /dev/null +++ b/src/main.hpp @@ -0,0 +1,9 @@ +extern "C" +{ + #include + #include +} + +#include "game.hpp" +#include "windmill.hpp" +#include "scene_map.hpp" diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 0000000..e679fca --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,1427 @@ +//----------------------------------------------------------------------------- +// +// MAP +// +// fichier ou sont enregistres les sprites, les textures, et les objets +// +// +// Ce fichier est compilé avec -Wp,-w et -Wno-missing-field-initializers. +// +//----------------------------------------------------------------------------- + +#include "windmill.hpp" + +// SPRITES +const unsigned char sprite_brique_base[]={ + 0xff,0xff,0xff,0xff, + 0xa0,0x80,0x81,0x80, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0xff,0xff,0xff,0xff, + 0x08,0x08,0x08,0x08, + 0x0c,0x08,0x08,0x08, + 0x0a,0x08,0x08,0x88, + 0xff,0xff,0xff,0xff, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0xff,0xff,0xff,0xff, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x18, + 0x08,0x08,0x08,0x10, + 0xff,0xff,0xff,0xff, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0x80,0x88,0x80,0x80, + 0xff,0xf7,0xff,0xff, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x0c, + 0x88,0x08,0x08,0x08, + 0xff,0xff,0xff,0xff, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0xff,0xff,0xff,0xff, + 0xdd,0xdc,0xdd,0xfd, + 0xdd,0xdd,0xdd,0xdd, + 0xff,0xff,0xff,0xff, +}; + +const unsigned char sprite_brique[]={ + 0x80,0x80,0x80,0x80, + 0xa0,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0xff,0xff,0xff,0xff, + 0x08,0x08,0x08,0x18, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x08, + 0xff,0xff,0xff,0xff, + 0x80,0xc0,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x81,0x80, + 0xff,0xff,0xfe,0xff, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x18, + 0x08,0x08,0x08,0x28, + 0xff,0xff,0xff,0xff, + 0x81,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80, + 0xff,0xff,0xff,0xff, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x18, + 0xff,0xff,0xff,0xff, + 0x80,0x80,0x80,0x80, + 0x80,0x80,0xc0,0x80, + 0x88,0x80,0xa0,0x80, + 0xf7,0xff,0xff,0xff, + 0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x18, + 0x08,0x08,0x48,0x08, + 0xff,0xff,0xff,0xff, +}; + +const unsigned char sprite_toit_tuile[]={ + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0x08,0x88,0x84,0x41, + 0x08,0x88,0x84,0x41, + 0x08,0x8c,0x8c,0x41, + 0x09,0x88,0x88,0x41, + 0x19,0x08,0x88,0x41, + 0x1d,0x18,0x8c,0x41, + 0xf7,0xb7,0xf6,0xe3, + 0x22,0xe6,0x33,0xbe, + 0x22,0x42,0x11,0x10, + 0x22,0x42,0x11,0x10, + 0x32,0x46,0x11,0x10, + 0x1e,0x65,0x39,0xd8, + 0xe5,0xdd,0xef,0x7d, + 0x84,0x84,0x44,0x27, + 0x84,0x84,0x44,0x21, + 0x8c,0x84,0x46,0x21, + 0xdc,0xcc,0x66,0x21, + 0x77,0xde,0xf7,0x73, + 0x42,0x73,0x9d,0xde, + 0x42,0x21,0x08,0x88, + 0x42,0x21,0x08,0x88, + 0x42,0x21,0x08,0x88, + 0x47,0x21,0x0d,0xdc, + 0xfd,0xf3,0x15,0x77, + 0x99,0x9e,0xf7,0x21, + 0x08,0x84,0x42,0x21, + 0x08,0x84,0x42,0x21, + 0x88,0x84,0x42,0x21, + 0x8d,0xcc,0xe6,0x73, + 0xff,0xff,0xff,0xff, +}; + +const unsigned char sprite_paille[]={ + 0x5a,0x95, + 0x58,0x95, + 0x5a,0x95, + 0x5e,0xd5, + 0xd2,0xd0, + 0xd3,0x59, + 0x93,0x59, + 0x37,0x49, + 0x36,0x49, + 0x26,0x49, + 0x24,0xcb, + 0xa4,0xeb, + 0xa9,0xaa, + 0xe9,0xaa, + 0x69,0xaa, + 0x49,0x8a, +}; + +const unsigned char sprite_paille_dessus[]={ + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, + 0x88,0x88, + 0x22,0x22, +}; + +const unsigned char sprite_mur_moulin[]={ + 0x81,0x02,0x08,0x73, + 0x81,0x02,0x08,0x4d, + 0x81,0x02,0x08,0x41, + 0x81,0x02,0x08,0x41, + 0x81,0x02,0x08,0x41, + 0x81,0x02,0x08,0x41, + 0x81,0x02,0x09,0xc1, + 0x81,0x1e,0x0e,0x41, + 0x81,0xe2,0x08,0x41, + 0x81,0x02,0x08,0x41, + 0x81,0x02,0x08,0x41, + 0x81,0x02,0x48,0x41, + 0x81,0x02,0xa8,0x41, + 0x81,0x03,0x18,0x79, + 0x81,0x02,0x08,0x47, + 0x81,0x02,0x08,0x41, + 0xf9,0x02,0x08,0x41, + 0x87,0x04,0x08,0x21, + 0x81,0x04,0x08,0x21, + 0x81,0x04,0x08,0x21, + 0x81,0x04,0x08,0x21, + 0x81,0x04,0x0e,0x61, + 0x81,0x04,0x09,0xa1, + 0x81,0x04,0x08,0x21, + 0x81,0x04,0x08,0x21, + 0x81,0x3c,0x08,0x21, + 0x81,0xc4,0x08,0x21, + 0x81,0x04,0x08,0x21, + 0x81,0x04,0x08,0x31, + 0x99,0x04,0x08,0x2f, + 0xe7,0x04,0x08,0x21, + 0x81,0x07,0xf8,0x21, +}; + +const unsigned char sprite_pale_moulin[]={ + 0xff,0xff, + 0x87,0xe1, + 0x87,0xe1, + 0x8f,0xf1, + 0x8f,0xf1, + 0x9b,0xd9, + 0x9b,0xd9, + 0xb3,0xcd, + 0xb3,0xcd, + 0xe7,0xe7, + 0xe7,0xe7, + 0xc7,0xe3, + 0xff,0xff, + 0xc7,0xe3, + 0xc7,0xe3, + 0xc7,0xe3, + 0xc7,0xe3, + 0xc7,0xe3, + 0xc5,0xa3, + 0xcd,0xb3, + 0xcd,0xb3, + 0xff,0xff, + 0xcd,0xb3, + 0xcd,0xb3, + 0xcd,0xb3, + 0xcd,0xb3, + 0xcd,0xb3, + 0xd9,0x9b, + 0xff,0xff, + 0xd9,0x9b, + 0xd9,0x9b, + 0xd9,0x9b, + 0xd9,0x9b, + 0xd9,0x9b, + 0xd9,0x9b, + 0xd9,0x9b, + 0xd1,0x8b, + 0xff,0xff, + 0xf1,0x8f, + 0xf1,0x8f, + 0xf1,0x8f, + 0xf1,0x8f, + 0xf1,0x8f, + 0xf1,0x8f, + 0xf1,0x8f, + 0xff,0xff, + 0xe1,0x87, + 0xe1,0x87, + 0xe1,0x87, + 0xe1,0x87, + 0xe1,0x87, + 0xe1,0x87, + 0xe1,0x87, + 0xe1,0x87, + 0xff,0xff, + 0xc1,0x83, + 0xc1,0x83, + 0xc1,0x83, + 0xc1,0x83, + 0xc1,0x83, + 0xc1,0x83, + 0xff,0xff, + 0xff,0xff, + 0xff,0xff, +}; + +const unsigned char sprite_fenetre_simple[]={ + 0xff,0xff, + 0xc1,0x03, + 0xc1,0x03, + 0xc1,0x03, + 0xc1,0x03, + 0xff,0xff, + 0xc1,0x03, + 0xc1,0x03, + 0xc1,0x03, + 0xff,0xff, + 0xc1,0x03, + 0xc1,0x03, + 0xc1,0x03, + 0xc1,0x03, + 0xff,0xff, + 0xff,0xff, +}; + +const unsigned char sprite_porte_simple[]={ + 0xff,0xff, + 0x80,0x01, + 0x80,0x01, + 0xff,0xff, + 0xff,0xff, + 0xe0,0x07, + 0xc9,0x43, + 0xc9,0x4b, + 0xc9,0x4b, + 0xc1,0x0b, + 0xc9,0x0b, + 0xc9,0x4b, + 0xc9,0x43, + 0xc8,0x43, + 0xc8,0x4b, + 0xc9,0x4b, + 0xc1,0x03, + 0xc9,0x3b, + 0xc9,0x3b, + 0xc9,0x2b, + 0xc9,0x13, + 0xc9,0x03, + 0xc8,0x03, + 0xc8,0x43, + 0xc8,0x43, + 0xc9,0x4b, + 0xc1,0x4b, + 0xc9,0x4b, + 0xc9,0x4b, + 0xc9,0x0b, + 0xc0,0x03, + 0xff,0xff, +}; + +const unsigned char sprite_pierre_eglise[]={ + 0xe0,0x00,0x00,0x07, + 0x20,0x00,0x00,0x04, + 0xe0,0x00,0x00,0x07, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0xe0,0x00,0x00,0x07, + 0x20,0x00,0x00,0x04, + 0xe0,0x00,0x00,0x07, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0xe0,0x00,0x00,0x07, + 0x20,0x00,0x00,0x04, + 0xe0,0x00,0x00,0x07, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, +}; + +const unsigned char sprite_pierre_eglise2[]={ + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0xe0,0x00,0x00,0x07, + 0x20,0x00,0x00,0x04, + 0xe0,0x00,0x00,0x07, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0xe0,0x00,0x00,0x07, + 0x20,0x00,0x00,0x04, + 0xe0,0x00,0x00,0x07, + 0x40,0x00,0x00,0x02, + 0x40,0x00,0x00,0x02, + 0xe0,0x00,0x00,0x07, + 0x20,0x00,0x00,0x04, + 0xe0,0x00,0x00,0x07, +}; + +const unsigned char sprite_horloge[]={ + 0x00,0x7f,0xfe,0x00, + 0x01,0x80,0x01,0x80, + 0x06,0x02,0xc0,0x60, + 0x08,0x82,0x41,0x10, + 0x10,0x02,0x80,0x08, + 0x24,0x02,0xc0,0x24, + 0x20,0x00,0x00,0x04, + 0x40,0x00,0x00,0x02, + 0x50,0x00,0x00,0x0a, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x90,0x00,0x00,0x0d, + 0xa8,0x01,0x80,0x05, + 0x98,0x01,0x80,0x0d, + 0x88,0x00,0x00,0x05, + 0x90,0x00,0x00,0x0d, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x50,0x00,0x00,0x12, + 0x40,0x00,0x00,0x02, + 0x20,0x01,0x00,0x04, + 0x24,0x02,0x00,0x24, + 0x10,0x03,0x00,0x08, + 0x08,0x82,0x81,0x10, + 0x06,0x01,0x00,0x60, + 0x01,0x80,0x01,0x80, + 0x00,0x7f,0xfe,0x00, +}; + +const unsigned char sprite_porte_eglise[]={ + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x3f,0xfc,0x00, + 0x00,0xc0,0x83,0x00, + 0x03,0x05,0x28,0xc0, + 0x04,0x90,0x03,0x20, + 0x0a,0x41,0x20,0x10, + 0x10,0x10,0x0a,0xa8, + 0x23,0x12,0x10,0x04, + 0x24,0x00,0x44,0x24, + 0x50,0xbf,0xfc,0x92, + 0x44,0xff,0xff,0x12, + 0x93,0xc1,0x83,0xc5, + 0xd7,0x01,0x80,0xe1, + 0x9c,0x01,0x80,0x35, + 0xf8,0x01,0x80,0x19, + 0xb0,0x01,0x80,0x0d, + 0xa0,0x01,0x80,0x05, + 0xe0,0x01,0x80,0x07, + 0xc0,0x01,0x80,0x83, + 0xc0,0x81,0x80,0x03, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x82,0x01, + 0x80,0x01,0x82,0x01, + 0xc0,0x01,0x82,0x03, + 0xc0,0x01,0x80,0x03, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x81,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x1d,0xb8,0x01, + 0x80,0x09,0x90,0x01, + 0x80,0x15,0xa8,0x01, + 0x80,0x09,0x90,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0xf1, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0xc0,0x01,0x80,0x03, + 0xc0,0x01,0x80,0x03, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0x80,0x01,0x80,0x01, + 0xff,0xff,0xff,0xff, +}; + +const unsigned char sprite_planche_bois[]={ + 0x81,0x04,0x08,0x20, + 0xff,0x04,0x08,0x20, + 0x81,0x04,0x08,0x20, + 0xa5,0x04,0x08,0x20, + 0x81,0x04,0x08,0x20, + 0x81,0x04,0x0a,0xa0, + 0x81,0x54,0x08,0x20, + 0x81,0x04,0x0f,0xe0, + 0x81,0xfc,0x08,0x20, + 0x81,0x04,0x0a,0xa0, + 0x81,0x54,0x08,0x20, + 0x81,0x05,0x28,0x2a, + 0x81,0x04,0x08,0x20, + 0x81,0x07,0xf8,0x3f, + 0x81,0x04,0x08,0x20, + 0xa5,0x05,0x28,0x24, + 0x81,0x04,0x08,0x20, + 0xff,0x04,0x08,0x20, + 0x81,0x04,0x08,0x20, + 0xa5,0x04,0x0a,0x20, + 0x81,0x04,0x08,0x20, + 0x81,0x04,0x0f,0xe0, + 0x81,0x04,0x08,0x20, + 0x81,0x54,0x0a,0xaa, + 0x81,0x04,0x08,0x20, + 0x81,0xfc,0x08,0x3f, + 0x81,0x04,0x08,0x20, + 0x81,0x04,0x08,0x2a, + 0x81,0x04,0x08,0x20, + 0x81,0x05,0x28,0x20, + 0x81,0x04,0x08,0x20, + 0xa5,0x07,0xf8,0x20, +}; + +const unsigned char sprite_haie[]={ + 0x80,0x01, + 0xff,0xff, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0xff,0xff, + 0x80,0x01, + 0x80,0x01, +}; + +const unsigned char sprite_epouvantail[]={ + 0x00,0x00, + 0x03,0x8c, + 0x06,0xd0, + 0x04,0x20, + 0x0f,0xf0, + 0x04,0x20, + 0x04,0x20, + 0x06,0x60, + 0x03,0xc0, + 0x01,0x80, + 0xe1,0x80, + 0xff,0xfc, + 0x3f,0xff, + 0x04,0x23, + 0x04,0xa0, + 0x04,0xa0, + 0x04,0x20, + 0x06,0x20, + 0x04,0x20, + 0x04,0x20, + 0x05,0x20, + 0x04,0x20, + 0x04,0x60, + 0x04,0xa0, + 0x07,0xe0, + 0x03,0xc0, + 0x03,0xc0, + 0x03,0xc0, + 0x01,0x80, + 0x01,0x80, + 0x01,0x80, + 0x01,0x80, +}; + +const unsigned char sprite_epouvantail_masque[]={ + 0x00,0x00, + 0x03,0x8c, + 0x07,0xd0, + 0x07,0xe0, + 0x0f,0xf0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x03,0xc0, + 0x01,0x80, + 0xe1,0x80, + 0xff,0xfc, + 0x3f,0xff, + 0x07,0xe3, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x07,0xe0, + 0x03,0xc0, + 0x03,0xc0, + 0x03,0xc0, + 0x01,0x80, + 0x01,0x80, + 0x01,0x80, + 0x01,0x80, +}; + +const unsigned char sprite_herbe[]={ + 0x08,0x00, + 0x48,0x20, + 0x49,0x22, + 0x44,0x92, + 0x44,0x94, + 0x25,0x15, + 0x25,0x15, + 0x25,0x15, +}; + +const unsigned char sprite_panneau[]={ + 0xff,0xff, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x92,0xb1, + 0xb5,0x95, + 0x94,0xb5, + 0x80,0x01, + 0x80,0x01, + 0x95,0x6d, + 0x95,0x45, + 0xa2,0x65, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0xff,0xff, +}; + +const unsigned char sprite_mur_int_maison[]={ + 0xff,0xff, + 0x98,0x19, + 0xb0,0x0d, + 0xe0,0x07, + 0xc0,0x03, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0xff,0xff, + 0xff,0xff, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0x91,0x11, + 0xff,0xff, +}; + +const unsigned char sprite_planche[]={ + 0xff,0xff,0xff,0xff, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x04,0x00,0x81, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x80,0x01, + 0x80,0x00,0x00,0x01, + 0x82,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x01, + 0x80,0x00,0x00,0x41, + 0x80,0x00,0x00,0x01, + 0xff,0xff,0xff,0xff, +}; + + +const unsigned char sprite_exemple[]={ + 0xff,0xff,0xff,0xff, + 0x87,0xff,0xfc,0x01, + 0xb4,0x00,0x05,0xfd, + 0xb4,0x00,0x05,0xfd, + 0x84,0x00,0x04,0x01, + 0xfc,0x00,0x07,0xff, + 0xc0,0x00,0x00,0x01, + 0xc0,0xfc,0x00,0x01, + 0xc3,0x86,0x00,0x01, + 0xcc,0x03,0x00,0x01, + 0xc9,0x99,0x00,0x01, + 0xc9,0x99,0x07,0xff, + 0xc8,0x01,0x04,0x01, + 0xc8,0x01,0x04,0x01, + 0xc8,0xf1,0x04,0x01, + 0xcc,0x62,0xff,0xff, + 0xc6,0x06,0x80,0x21, + 0xc3,0xfc,0x80,0x21, + 0xc0,0x00,0x80,0x21, + 0xc0,0x00,0xff,0xff, + 0xc0,0x00,0x04,0x01, + 0xc0,0x00,0x04,0x01, + 0xc0,0x00,0x04,0x01, + 0xc0,0x00,0x07,0xff, + 0xc0,0x00,0x00,0x01, + 0xc0,0x00,0x80,0x01, + 0xfc,0x01,0xc0,0x3f, + 0xc4,0x03,0xe0,0x3f, + 0xa4,0x07,0x70,0x33, + 0x94,0x0e,0x38,0x33, + 0x8f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, +}; + +/* +const unsigned char sprite_mur_colombage[]={ + 0xff,0xff,0xff,0xff, + 0xc0,0x00,0x00,0x03, + 0xc0,0x00,0x00,0x03, + 0xe0,0x00,0x00,0x07, + 0xe0,0x3f,0xfc,0x07, + 0xe0,0x20,0x84,0x07, + 0xb0,0x20,0x84,0x0d, + 0xb0,0x20,0x84,0x0d, + 0xb0,0x20,0x84,0x0d, + 0x98,0x20,0x84,0x19, + 0x98,0x3f,0xfc,0x19, + 0x98,0x20,0x84,0x19, + 0x8c,0x20,0x84,0x31, + 0x8c,0x20,0x84,0x31, + 0xff,0xe0,0x87,0xff, + 0xff,0xe0,0x87,0xff, + 0x86,0x20,0x84,0x61, + 0x83,0x3f,0xfc,0xe1, + 0x83,0x20,0x84,0xc1, + 0x83,0x20,0x84,0xc1, + 0x81,0xa0,0x85,0x81, + 0x81,0xa0,0x85,0x81, + 0x81,0xbf,0xfd,0x81, + 0x80,0xc0,0x03,0x01, + 0x80,0xc0,0x03,0x01, + 0x80,0xc0,0x03,0x01, + 0x80,0x60,0x06,0x01, + 0x80,0x60,0x06,0x01, + 0x80,0x60,0x06,0x01, + 0x80,0x30,0x0c,0x01, + 0x80,0x30,0x0c,0x01, + 0xff,0xff,0xff,0xff, +}; + +const unsigned char sprite_plaque_egout[]={ + 0x07,0xe0, + 0x18,0x18, + 0x21,0x04, + 0x40,0x02, + 0x48,0x82, + 0x80,0x01, + 0x80,0x11, + 0x82,0x21, + 0x84,0x81, + 0x80,0x21, + 0x90,0x01, + 0x41,0x02, + 0x40,0x02, + 0x20,0x04, + 0x18,0x18, + 0x07,0xe0, +}; + + + +const unsigned char sprite_pancarte_forgeron[]={ + 0xff,0xff, + 0x80,0x01, + 0x80,0x01, + 0x80,0x01, + 0xbf,0x81, + 0xbf,0xfd, + 0x9f,0xf9, + 0x87,0xe1, + 0x87,0xe1, + 0x83,0xc1, + 0x83,0xc1, + 0x8f,0xf1, + 0x9f,0xf9, + 0x80,0x01, + 0x80,0x01, + 0xff,0xff, +}; + + + +const unsigned char sprite_comptoire[]={ + 0x88,0x88, + 0x88,0x88, + 0x88,0x88, + 0x88,0x88, + 0xaa,0xaa, + 0x88,0x88, + 0x88,0x88, + 0x88,0x88, +}; + +const unsigned char sprite_trappe[]={ + 0xff,0xff, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x89, + 0x88,0x09, + 0x89,0xc9, + 0x89,0x49, + 0x89,0xc9, + 0x88,0x09, + 0xff,0xff, +}; + + + +const unsigned char sprite_arbre1[]={ + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x07,0x80,0x00, + 0x00,0x08,0x7c,0x00, + 0x00,0x10,0x04,0x00, + 0x03,0x60,0x0b,0x80, + 0x04,0x80,0x04,0x40, + 0x04,0x00,0x00,0x40, + 0x04,0x00,0x00,0x20, + 0x08,0x78,0x00,0x10, + 0x14,0x07,0xc0,0x08, + 0x12,0x00,0x00,0x04, + 0x20,0x00,0x00,0x04, + 0x40,0x00,0x00,0x06, + 0x40,0x00,0x00,0xc6, + 0x40,0x00,0x03,0x04, + 0xe0,0x01,0x3c,0x04, + 0xa0,0x01,0xc0,0x06, + 0x9e,0x80,0x00,0x02, + 0x83,0x80,0x00,0x02, + 0x80,0x00,0x00,0x02, + 0x80,0x00,0x00,0x02, + 0x80,0x00,0x00,0x03, + 0x80,0x00,0x00,0x05, + 0x80,0x00,0x0c,0x05, + 0x88,0x00,0x0c,0x1d, + 0x88,0x1f,0x00,0x01, + 0x4e,0x08,0x00,0x06, + 0x70,0x00,0x00,0x01, + 0x10,0x00,0x00,0x01, + 0x60,0x00,0x00,0x01, + 0x40,0x00,0x30,0x09, + 0x50,0x00,0xc0,0x05, + 0x50,0x00,0x00,0x0e, + 0x40,0x00,0x00,0x08, + 0x48,0x00,0x00,0x84, + 0x74,0x00,0x00,0x04, + 0x07,0x7f,0x80,0xf8, + 0x00,0x89,0xff,0x80, + 0x00,0x06,0x51,0x00, + 0x00,0x05,0x50,0x80, + 0x00,0x04,0x10,0x00, + 0x00,0x04,0xd0,0x00, + 0x00,0x04,0xd0,0x00, + 0x00,0x04,0x10,0x00, + 0x00,0x04,0x90,0x00, + 0x00,0x05,0x30,0x00, + 0x00,0x05,0x30,0x00, + 0x00,0x05,0x30,0x00, + 0x00,0x05,0x30,0x00, + 0x00,0x04,0x10,0x00, + 0x00,0x04,0x10,0x00, + 0x00,0x06,0x10,0x00, + 0x00,0x05,0x50,0x00, + 0x00,0x04,0x50,0x00, + 0x00,0x04,0x50,0x00, + 0x00,0x04,0x90,0x00, + 0x00,0x04,0x50,0x00, + 0x00,0x04,0x30,0x00, + 0x00,0x05,0x10,0x00, + 0x00,0x05,0x10,0x00, + 0x00,0x0f,0x78,0x00, + 0x00,0x31,0xc4,0x00, + 0x00,0x02,0x20,0x00, +}; + +const unsigned char mask_arbre1[]={ + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x07,0x80,0x00, + 0x00,0x0f,0xfc,0x00, + 0x00,0x1f,0xfc,0x00, + 0x03,0x7f,0xfb,0x80, + 0x07,0xff,0xff,0xc0, + 0x07,0xff,0xff,0xc0, + 0x07,0xff,0xff,0xe0, + 0x0f,0xff,0xff,0xf0, + 0x1f,0xff,0xff,0xf8, + 0x1f,0xff,0xff,0xfc, + 0x3f,0xff,0xff,0xfc, + 0x7f,0xff,0xff,0xfe, + 0x7f,0xff,0xff,0xfe, + 0x7f,0xff,0xff,0xfc, + 0xff,0xff,0xff,0xfc, + 0xff,0xff,0xff,0xfe, + 0xff,0xff,0xff,0xfe, + 0xff,0xff,0xff,0xfe, + 0xff,0xff,0xff,0xfe, + 0xff,0xff,0xff,0xfe, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff, + 0x7f,0xff,0xff,0xfe, + 0x7f,0xff,0xff,0xff, + 0x1f,0xff,0xff,0xff, + 0x7f,0xff,0xff,0xff, + 0x7f,0xff,0xff,0xff, + 0x7f,0xff,0xff,0xff, + 0x7f,0xff,0xff,0xfe, + 0x7f,0xff,0xff,0xf8, + 0x7f,0xff,0xff,0xfc, + 0x77,0xff,0xff,0xfc, + 0x07,0xff,0xff,0xf8, + 0x00,0x8f,0xff,0x80, + 0x00,0x07,0xf1,0x00, + 0x00,0x07,0xf0,0x80, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x07,0xf0,0x00, + 0x00,0x0f,0xf8,0x00, + 0x00,0x31,0xc4,0x00, + 0x00,0x02,0x20,0x00, +}; +*/ +// Personnages +const unsigned char sprite_forgeron[]={ + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x07,0xc0,0x00, + 0x00,0x18,0x30,0x00, + 0x00,0x20,0x08,0x00, + 0x00,0x2f,0xe8,0x00, + 0x00,0x24,0x48,0x00, + 0x00,0x25,0x48,0x00, + 0x00,0x21,0x08,0x00, + 0x00,0x20,0x08,0x00, + 0x00,0x23,0x88,0x00, + 0x00,0x30,0x18,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x1f,0xf0,0x00, + 0x03,0xff,0xff,0xc0, + 0x04,0x6f,0xe6,0x20, + 0x08,0x63,0x86,0x10, + 0x08,0x50,0x09,0x10, + 0x08,0x90,0x09,0x10, + 0x08,0x8f,0xf1,0x10, + 0x08,0x80,0x03,0x90, + 0x08,0xe1,0xfe,0x50, + 0x08,0xfe,0x02,0x50, + 0x08,0x80,0x03,0xd0, + 0x08,0x01,0xfe,0x10, + 0x08,0x0f,0xf0,0x10, + 0x07,0xf0,0x0f,0xe0, + 0x01,0x00,0x00,0x80, + 0x01,0x00,0x00,0x80, + 0x01,0x00,0x00,0x80, + 0x01,0x00,0x00,0x80, + 0x01,0x00,0x70,0x80, + 0x01,0x00,0x70,0x80, + 0x01,0x00,0x24,0x80, + 0x01,0x10,0x28,0x80, + 0x01,0x0f,0xf0,0x80, + 0x02,0x00,0x00,0x40, + 0x02,0x00,0x00,0x40, + 0x02,0x00,0x10,0x40, + 0x02,0x0c,0x60,0x40, + 0x02,0x00,0x00,0x40, + 0x03,0xff,0xff,0xc0, + 0x00,0x42,0x42,0x00, + 0x00,0x5a,0x5a,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x42,0x42,0x00, + 0x00,0x5a,0x5a,0x00, + 0x00,0x66,0x66,0x00, + 0x00,0x66,0x66,0x00, + 0x00,0x7e,0x7e,0x00, +}; + +const unsigned char mask_forgeron[]={ + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x07,0xc0,0x00, + 0x00,0x1f,0xf0,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x3f,0xf8,0x00, + 0x00,0x1f,0xf0,0x00, + 0x03,0xff,0xff,0xc0, + 0x07,0xff,0xff,0xe0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xf0, + 0x07,0xff,0xff,0xe0, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x01,0xff,0xff,0x80, + 0x03,0xff,0xff,0xc0, + 0x03,0xff,0xff,0xc0, + 0x03,0xff,0xff,0xc0, + 0x03,0xff,0xff,0xc0, + 0x03,0xff,0xff,0xc0, + 0x03,0xff,0xff,0xc0, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, + 0x00,0x7e,0x7e,0x00, +}; + +// TEXTURE +Texture tex_white = {}; +Texture tex_light = {}; +Texture tex_dark = {}; +Texture tex_black = {}; + +const Texture tex_brique_base = {sprite_brique_base, NULL, 32, 32, 30, 30, 0.5, false, false}; +const Texture tex_brique = {sprite_brique, NULL, 32, 32, 30, 30, 0.5, false, false}; +const Texture tex_toit_tuile = {sprite_toit_tuile, NULL, 32, 32, 15, 15, 0.5, false, false}; +const Texture tex_paille = {sprite_paille, NULL, 16, 16, 10, 10, 0, false, false}; +const Texture tex_paille_dessus = {sprite_paille_dessus, NULL, 16, 16, 10, 10, 0, false, false}; +const Texture tex_mur_moulin = {sprite_planche_bois, NULL, 32, 32, 25, 25, 0.5, false, false}; +const Texture tex_pale_moulin = {sprite_pale_moulin, NULL, 16, 64, 0, 0, 0.5, false, false}; +const Texture tex_fenetre_simple = {sprite_fenetre_simple, NULL, 16, 16, 0, 0, 0, false, true}; +const Texture tex_porte_simple = {sprite_porte_simple, NULL, 16, 32, 0, 0, 0, false, true}; +const Texture tex_porte_entrepot = {sprite_planche_bois, NULL, 32, 32, 25, 25, 0, false, true}; +const Texture tex_pierre_eglise = {sprite_pierre_eglise, NULL, 32, 16, 0, 15, 0, false, false}; +const Texture tex_pierre_eglise2 = {sprite_pierre_eglise2, NULL, 32, 16, 0, 15, 0, false, false}; +const Texture tex_horloge = {sprite_horloge, NULL, 32, 32, 0, 0, 0, false, true, false}; +const Texture tex_porte_eglise = {sprite_porte_eglise, NULL, 32, 64, 0, 0, 0, false, true}; +const Texture tex_planche_bois = {sprite_planche_bois, NULL, 32, 32, 15, 15, 0.5, false, false}; +const Texture tex_haie = {sprite_haie, NULL, 16, 8, 20, 0, 0, true}; +const Texture tex_epouvantail = {sprite_epouvantail, sprite_epouvantail_masque, 16, 32, 0, 0, 0, false}; +const Texture tex_herbe = {sprite_herbe, NULL, 16, 8, 7, 0, 0, true}; +const Texture tex_panneau = {sprite_panneau, NULL, 16, 16, 0, 0, 0, false, true}; +const Texture tex_forgeron = {sprite_forgeron, mask_forgeron, 32, 64, 0, 0}; +const Texture tex_mur_int_maison = {sprite_mur_int_maison, NULL, 16, 32, 15, 0}; +const Texture tex_planche = {sprite_planche, NULL, 32, 16, 0, 0}; + + + + + +// MODELES +#define L1 20 // longueur extension X +#define W1 15 // largueur extension Y +#define H1 30 // hauteur mur Z +#define HT1 45 // hauteur toit nef Z +#define D 5 // decalage toit XY +#define L2 80 // longueur tour X +#define W2 20 // largeur tour X +#define H2 70 // hauteur mur tour Z +#define HT2 90 // hauteur toit tour Z +#define L3 (L1+(L2-L1)/2) // milieu toit tour X +const Modele modele_moulin[] = { + // les murs extension + {RECTANGLE, &tex_white, NULL, L1,W1,0, -L1,W1,0, L1,W1,H1}, + {RECTANGLE, &tex_brique, NULL, -L1,W1,0, -L1,-W1,0, -L1,W1,H1}, + {RECTANGLE, &tex_white, NULL, -L1,-W1,0, L1,-W1,0, -L1,-W1,H1}, + // la tour + {RECTANGLE, &tex_mur_moulin, NULL, L2,-W2,0, L2,W2,0, L2,-W2,H2}, + {RECTANGLE, &tex_mur_moulin, NULL, L2,W2,0, L1,W2,0, L2,W2,H2}, + {RECTANGLE, &tex_mur_moulin, NULL, L1,W2,0, L1,-W2,0, L1,W2,H2}, + {RECTANGLE, &tex_mur_moulin, NULL, L1,-W2,0, L2,-W2,0, L1,-W2,H2}, + // prolongement mur nef jusqu au toit + {TRIANGLE, &tex_brique, NULL, -L1,W1,H1, -L1,-W1,H1, -L1,0,HT1}, + // le toit de l extension + {RECTANGLE, &tex_paille, &tex_black, L1,W1+D,H1-3, -L1-D,W1+D,H1-3, L1,0,HT1}, + {RECTANGLE, &tex_paille, &tex_black, -L1-D,-W1-D,H1-3, L1,-W1-D,H1-3, -L1-D,0,HT1}, + // prolongement mur nef jusqu au toit + {TRIANGLE, &tex_mur_moulin, NULL, L2,W2,H2, L1,W2,H2, L3,W2,HT2}, + {TRIANGLE, &tex_mur_moulin, NULL, L1,-W2,H2, L2,-W2,H2, L3,-W2,HT2}, + // le toit de la tour + {RECTANGLE, &tex_toit_tuile, NULL, L2,-W2,H2, L2,W2,H2, L3,-W2,HT2}, + {RECTANGLE, &tex_toit_tuile, NULL, L1,W2,H2, L1,-W2,H2, L3,W2,HT2}, +}; + +#define A 3 // angle pale +const Modele modele_pale[] = { + {TRIANGLE, &tex_pale_moulin, &tex_pale_moulin, -21,-A,56, 21,A,56, 0,0,0}, + {TRIANGLE, &tex_pale_moulin, &tex_pale_moulin, 47,-A,36, 60,A,-2, 0,0,0}, + {TRIANGLE, &tex_pale_moulin, &tex_pale_moulin, 50,-A,-34, 17,A,-58, 0,0,0}, + {TRIANGLE, &tex_pale_moulin, &tex_pale_moulin, -17,-A,-58, -50,A,-34, 0,0,0}, + {TRIANGLE, &tex_pale_moulin, &tex_pale_moulin, -60,-A,-2, -47,A,37, 0,0,0}, +}; + + +#define L 40 // longueur X +#define W 20 // largueur Y +#define H 30 // hauteur mur Z +#define HT 55 // hauteur toit Z +#define D 5 // decalage toit XY +#define F1 10 // position X fenetre +#define F2 10 // position X fenetre +#define P -20 // position X fporte +const Modele modele_chaumiere[] = { + // les murs + {RECTANGLE, &tex_brique_base, NULL, L,-W,0, L,W,0, L,-W,H}, + {RECTANGLE, &tex_white, NULL, L,W,0, -L,W,0, L,W,H}, + {RECTANGLE, &tex_brique_base, NULL, -L,W,0, -L,-W,0, -L,W,H}, + {RECTANGLE, &tex_white, NULL, -L,-W,0, L,-W,0, -L,-W,H}, + // prolongement mur jusqu au toit + {TRIANGLE, &tex_brique, NULL, L,-W,H, L,W,H, L,0,HT}, + {TRIANGLE, &tex_brique, NULL, -L,W,H, -L,-W,H, -L,0,HT}, + // le toit + {RECTANGLE, &tex_paille, &tex_black, L+D,W+D,H-3, -L-D,W+D,H-3, L+D,0,HT}, + {RECTANGLE, &tex_paille, &tex_black, -L-D,-W-D,H-3, L+D,-W-D,H-3, -L-D,0,HT}, + // fenetre + {RECTANGLE, &tex_fenetre_simple, NULL, F1,W,8, F1-9,W,8, F1,W,25}, + {RECTANGLE, &tex_fenetre_simple, NULL, F2,-W,8, F2+9,-W,8, F2,-W,25}, + // porte + {RECTANGLE, &tex_porte_simple, NULL, P,W,0, P-12,W,0, P,W,25}, +}; + + +#define L 80 // longueur X +#define W 30 // largueur Y +#define H 35 // hauteur mur Z +#define HT 55 // hauteur toit Z +#define P -20 // position X fporte +const Modele modele_entrepot[] = { + // les murs + {RECTANGLE, &tex_brique, NULL, L,-W,0, L,W,0, L,-W,H}, + {RECTANGLE, &tex_white, NULL, L,W,0, -L,W,0, L,W,HT}, + {RECTANGLE, &tex_brique, NULL, -L,W,0, -L,-W,0, -L,W,H}, + {RECTANGLE, &tex_white, NULL, -L,-W,0, L,-W,0, -L,-W,H}, + // prolongement mur jusqu au toit + {TRIANGLE, &tex_white, NULL, L,-W,H, L,W,H, L,W,HT}, + {TRIANGLE, &tex_white, NULL, -L,W,H, -L,-W,H, -L,W,HT}, + // le toit + {RECTANGLE, &tex_paille, &tex_black, -L-D,-W-D,H-3, L+D,-W-D,H-3, -L-D,W+D,HT}, + // porte + {RECTANGLE, &tex_planche_bois, NULL, P,W+2,0, P-35,W+2,0, P,W+1,40}, + // glissiere + {RECTANGLE, &tex_black, NULL, P+35,W+2,0, P-40,W+2,0, P+35,W+1,1}, + {RECTANGLE, &tex_black, NULL, P+35,W+2,40, P-40,W+2,40, P+35,W+1,41}, +}; + + +#define LN 50 // longueur nef X +#define WN 22 // largueur nef Y +#define HN 60 // hauteur mur nef Z +#define HNT 80 // hauteur toit nef Z +#define D 5 // decalage toit XY +#define LT 90 // longueur tour X +#define WT 28 // largeur tour X +#define HT 100 // hauteur mur tour Z +#define HH 70 // hauteur horloge Z +#define HC 120 // hauteur clocher Z +#define HCT 150 // hauteur clocher max Z +const Modele modele_eglise[] = { + // les murs nefs + {RECTANGLE, &tex_white, NULL, LN,WN,0, -LN,WN,0, LN,WN,HN}, + {RECTANGLE, &tex_brique, NULL, -LN,WN,0, -LN,-WN,0, -LN,WN,HN}, + {RECTANGLE, &tex_white, NULL, -LN,-WN,0, LN,-WN,0, -LN,-WN,HN}, + // la tour + {RECTANGLE, &tex_pierre_eglise, NULL, LT,-WT,0, LT,WT,0, LT,-WT,HT}, + {RECTANGLE, &tex_pierre_eglise, NULL, LT,WT,0, LN,WT,0, LT,WT,HT}, + {RECTANGLE, &tex_pierre_eglise, NULL, LN,WT,0, LN,-WT,0, LN,WT,HT}, + {RECTANGLE, &tex_pierre_eglise, NULL, LN,-WT,0, LT,-WT,0, LN,-WT,HT}, + // prolongement mur nef jusqu au toit + {TRIANGLE, &tex_brique, NULL, -LN,WN,HN, -LN,-WN,HN, -LN,0,HNT}, + // le toit de la nef + {RECTANGLE, &tex_toit_tuile, &tex_black, LN,WN+D,HN-3, -LN-D,WN+D,HN-3, LN,0,HNT}, + {RECTANGLE, &tex_toit_tuile, &tex_black, -LN-D,-WN-D,HN-3, LN,-WN-D,HN-3, -LN-D,0,HNT}, + // horloge + {RECTANGLE, &tex_horloge, NULL, LT,-10,HH, LT,10,HH, LT,-10,HH+20}, + // porte + {RECTANGLE, &tex_porte_eglise, NULL, LT,-15,0, LT,15,0, LT,-15,60}, + // clocher + {TRIANGLE, &tex_toit_tuile, NULL, LT,-WT,HT, LT,WT,HT, 70,0,HCT}, + {TRIANGLE, &tex_toit_tuile, NULL, LT,WT,HT, LN,WT,HT, 70,0,HCT}, + {TRIANGLE, &tex_toit_tuile, NULL, LN,WT,HT, LN,-WT,HT, 70,0,HCT}, + {TRIANGLE, &tex_toit_tuile, NULL, LN,-WT,HT, LT,-WT,HT, 70,0,HCT}, +}; + + +#define L 30// longueur X +#define H 10// hauteur Z +const Modele modele_haie1[] = { + {RECTANGLE, &tex_haie, &tex_haie, -L,0,0, L,0,0, -L,0,H} +}; + +#define L 50// longueur X +#define H 10// hauteur Z +const Modele modele_haie2[] = { + {RECTANGLE, &tex_haie, &tex_haie, -L,0,0, L,0,0, -L,0,H} +}; + +#define L 10// longueur X +#define H 19// hauteur Z +const Modele modele_epouventail1[] = { + {RECTANGLE, &tex_epouvantail, &tex_epouvantail, -L,0,0, L,0,0, -L,0,H} +}; + +#define L 60// longueur X +#define H 9// hauteur Z +const Modele modele_herbe1[] = { + {RECTANGLE, &tex_herbe, &tex_herbe, -L,0,0, L,0,0, -L,0,H} +}; + +#define L 60// longueur X +#define H 9// hauteur Z +const Modele modele_herbe2[] = { + {RECTANGLE, &tex_herbe, &tex_herbe, -L,0,0, L,0,0, -L,0,H} +}; + +#define L 4// longueur X +#define H1 13// hauteur Z +#define H2 18// hauteur Z +const Modele modele_panneau1[] = { + {RECTANGLE, &tex_panneau, &tex_panneau, -L,0,H1, L,0,H1, -L,0,H2}, + {RECTANGLE, &tex_black, &tex_black, -L-1,0,0, -L,0,0, -L-1,0,H2}, + {RECTANGLE, &tex_black, &tex_black, L,0,0, L+1,0,0, L,0,H2} +}; + +#define L 7 // longueur X +#define W 7 // largueur Y +#define H 14 // hauteur Z +const Modele modele_botte_paille[] = { + // les cotes + {RECTANGLE, &tex_paille, NULL, L,-W,0, L,W,0, L,-W,H}, + {RECTANGLE, &tex_paille, NULL, L,W,0, -L,W,0, L,W,H}, + {RECTANGLE, &tex_paille, NULL, -L,W,0, -L,-W,0, -L,W,H}, + {RECTANGLE, &tex_paille, NULL, -L,-W,0, L,-W,0, -L,-W,H}, + // dessus + {RECTANGLE, &tex_paille_dessus, NULL, -L,-W,H, L,-W,H, -L,W,H}, +}; + +#define L 50 // longueur X +#define W 25 // largueur Y +#define H 25 // hauteur Z +const Modele modele_murs_maison_forgeron[] = { + // les cotes + {RECTANGLE, NULL, &tex_mur_int_maison, L,-W,0, L,W,0, L,-W,H}, + {RECTANGLE, NULL, &tex_mur_int_maison, L,W,0, -L,W,0, L,W,H}, + {RECTANGLE, NULL, &tex_mur_int_maison, -L,W,0, -L,-W,0, -L,W,H}, + {RECTANGLE, NULL, &tex_mur_int_maison, -L,-W,0, L,-W,0, -L,-W,H}, + //plafond + {RECTANGLE, NULL, &tex_black, -L,-W,H, L,-W,H, -L,W,H}, +}; + +#define L 10 // longueur X +#define W 4 // largueur Y +#define H 7 // hauteur Z +#define D 1 // decalage pied +#define E 1 // epaisseur pied +const Modele modele_table[] = { + // planche + {RECTANGLE, &tex_planche, &tex_black, -L,-W,H, L,-W,H, -L,W,H}, + // pieds + {RECTANGLE, &tex_black, &tex_black, -L+D,-W+D,0, -L+D+E,-W+D+E,0, -L+D,-W+D,H-1}, + {RECTANGLE, &tex_black, &tex_black, L-D,-W+D,0, L-D-E,-W+D+E,0, L-D,-W+D,H-1}, + {RECTANGLE, &tex_black, &tex_black, -L+D,W-D,0, -L+D+E,W-D-E,0, -L+D,W-D,H-1}, + {RECTANGLE, &tex_black, &tex_black, L-D,W-D,0, L-D-E,W-D-E,0, L-D,W-D,H-1}, +}; + +#define W 7 // largueur Y +#define H 20 // hauteur Z +const Modele modele_forgeron[] = { + {RECTANGLE, &tex_forgeron, NULL, 0,-W,0, 0,W,0, 0,-W,H}, +}; + + + +// MAP +// ECRAN TITRE +Object moulin_menu = {0,0,0, 0,N, modele_moulin,14, NONE}; +Object pale_menu = {50,27,70, 0,Y, modele_pale,5, NONE}; + +Object* list_menu[] = { + &moulin_menu, &pale_menu +}; + +Map map_menu = {list_menu, 2, true, true}; + + + + + +// VILLAGE +Object chaumiere1 = {-36,62,0, 0,N, modele_chaumiere,11, ALL}; +Object chaumiere2 = {-153,194,0, 251,Z, modele_chaumiere,11, ALL}; +Object chaumiere3 = {0,257,0, 143,Z, modele_chaumiere,11, ALL}; +Object entrepot = {319,-57,0, 80,Z, modele_entrepot,10, ALL}; +Object eglise1 = {153,253,0, -102,Z, modele_eglise,16, ALL}; +Object moulin1 = {21,-211,0, 0,N, modele_moulin,14, ALL}; +Object pale_moulin1 = {72,-183,70, 0,Y, modele_pale,5, NONE}; +Object haie1 = {0,-102,0, -5,Z, modele_haie1,1, ALL}; +Object haie2 = {-63,-105,0, 9,Z, modele_haie1,1, ALL}; +Object haie3 = {-132,-144,0, 46,Z, modele_haie2,1, ALL}; +Object haie4 = {144,-135,0, -14,Z, modele_haie2,1, ALL}; +Object haie5 = {-117,-264,0, -30,Z, modele_haie2,1, ALL}; +Object epouvantail1 = {-93,-210,0, -28,Z, modele_epouventail1,1, ALL}; +Object herbe1 = {-130,-200,0, 90,Z, modele_herbe1,1, NONE}; +Object herbe2 = {-109,-200,0, 90,Z, modele_herbe1,1, NONE}; +Object herbe3 = {-82,-191,0, 90,Z, modele_herbe1,1, NONE}; +Object herbe4 = {-61,-185,0, 90,Z, modele_herbe1,1, NONE}; +Object herbe5 = {-37,-179,0, 90,Z, modele_herbe1,1, NONE}; +Object herbe6 = {235,119,0, 131,Z, modele_herbe1,1, NONE}; +Object herbe7 = {292,51,0, 94,Z, modele_herbe1,1, NONE}; +Object panneau1 = {91,-117,0, 0,N, modele_panneau1,3, ALL}; +Object botte_paille1 = {269,42,0, 0,N, modele_botte_paille,5, ALL}; +Object botte_paille2 = {269,21,0, 0,N, modele_botte_paille,5, ALL}; +Object botte_paille3 = {272,30,14, 0,N, modele_botte_paille,5, ALL}; + +Object* list_village[] = { + &chaumiere1, &chaumiere2, &chaumiere3, &entrepot, &eglise1, &moulin1, + &pale_moulin1, &haie1, &haie2, &haie3, &haie4, &haie5, &epouvantail1, + &herbe1, &herbe2, &herbe3, &herbe4, &herbe5, &herbe6, &herbe7, &panneau1, + &botte_paille1, &botte_paille2, &botte_paille3 +}; + +Map map_village = {list_village, 24, true, true}; + + + + + +// CHEZ LE FORGERON +Object murs_maison_forgeron1 = {0,0,0, 0,N, modele_murs_maison_forgeron,5, INSIDE}; +Object table1 = {18,17,0, 0,N, modele_table,5, ALL}; +Object table2 = {-23,-7,0, 99,Z, modele_table,5, ALL}; +Object forgeron1 = {-34,-8,0, 0,Z_BILLBOARD, modele_forgeron,1, ALL}; + +Object* liste_interieur_forgeron[] = { + &murs_maison_forgeron1, &table1, &table2, &forgeron1 +}; +Map map_interieur_forgeron = {liste_interieur_forgeron, 4, false, false}; + + + + + +// EXEMPLE +const Texture tex_exemple = {sprite_exemple, NULL, 32, 32, 0, 0, 1, false, false, false}; +//const Texture tex_exemple_mask = {sprite_forgeron, mask_forgeron, 32, 64, 0, 0, 1, false, false, false}; + +#define L 50 // longueur X +#define W 25 // largueur Y +#define W2 12 // largeur divise par deux +#define H 30 // hauteur mur Z +#define HT 40 // hauteur toit +#define F 20 // fenetre +const Modele modele_maison[] = { + // les murs + {RECTANGLE, &tex_white, NULL, 0,0,0, L,0,0, 0,0,H}, + {RECTANGLE, &tex_brique_base, NULL, L,0,0, L,W,0, L,0,H}, + {RECTANGLE, &tex_white, NULL, L,W,0, 0,W,0, L,W,H}, + {RECTANGLE, &tex_brique_base, NULL, 0,W,0, 0,0,0, 0,W,H}, + // prolongement mur jusqu au toit + {TRIANGLE, &tex_brique, NULL, L,0,H, L,W,H, L,W2,HT}, + {TRIANGLE, &tex_brique, NULL, 0,W,H, 0,0,H, 0,W2,HT}, + // le toit + {RECTANGLE, &tex_paille, NULL, L,W,H, 0,W,H, L,W2,HT}, + {RECTANGLE, &tex_paille, NULL, 0,0,H, L,0,H, 0,W2,HT}, + // fenetre + {RECTANGLE, &tex_fenetre_simple, NULL, F,0,7, F+9,0,7, F,0,25}, + {RECTANGLE, &tex_fenetre_simple, NULL, F,W,7, F-9,W,7, F,W,25}, +}; + +Object maison1 = { 33,-50, 0, 0, N, modele_maison, 10, ALL}; +Object maison2 = {100, 12, 0, 90, Z, modele_maison, 10, ALL}; + +Object* liste_exemple[] = { + &maison1, &maison2 +}; + +Map map_exemple = {liste_exemple, 2, true, true}; diff --git a/src/player.cpp b/src/player.cpp new file mode 100644 index 0000000..7dbe43b --- /dev/null +++ b/src/player.cpp @@ -0,0 +1,49 @@ +#include "player.hpp" + +//----------------------------------------------------------------------------- +// PLAYER +//----------------------------------------------------------------------------- +Player::Player() +{ + x = 0; + y = 0; + z = 0; + yaw = 0; + pitch = 0; + + height = 16;//16 + total_height = 18; + belly = 5; + + action_distance = 20; + + moving = false; + jumping = false; + turning = false; + + translation_speed = 0; + rotation_speed = 0; + jump_speed = 0; + + translation_speed_max = 1.5; + translation_acceleration = 0.1; + rotation_speed_max = 7; + int hauteur_saut_max = 2; // en metre + jump_speed_max = sqrtf(hauteur_saut_max * 2 * 9.81); + + dissociate_camera = false; + can_move = true; +} + + +//----------------------------------------------------------------------------- +// TELEPORT +//----------------------------------------------------------------------------- +void Player::teleport(float _x, float _y, float _z, float _yaw, float _pitch) +{ + x = _x; + y = _y; + z = _z; + yaw = _yaw; + pitch = _pitch; +} diff --git a/src/player.hpp b/src/player.hpp new file mode 100644 index 0000000..b8121ab --- /dev/null +++ b/src/player.hpp @@ -0,0 +1,52 @@ +#ifndef DEF_PLAYER +#define DEF_PLAYER + +extern "C" +{ + #define __BSD_VISIBLE 1 + #include +} + + + +#define MAP_EXTERIOR_LIMIT 1000 +#define COL_NO 0 +#define COL_GROUND 1 +#define COL_WALL 2 +#define COL_ON 3 +#define COL_CARA 4 +#define COL_BOUND 5 + + + +class Player +{ +public: + Player(); + void teleport(float _x, float _y, float _z, float _yaw, float _pitch); + + float x, y, z, yaw, pitch; + + bool moving, jumping, turning; + + float height; + float total_height; + float belly; + + float action_distance; + + float translation_speed; + float rotation_speed; + float jump_speed; + + float translation_speed_max; + float translation_acceleration; + float rotation_speed_max; + float jump_speed_max; + + bool dissociate_camera; + bool can_move; +}; + + +#endif diff --git a/src/scene_map.cpp b/src/scene_map.cpp new file mode 100644 index 0000000..3774210 --- /dev/null +++ b/src/scene_map.cpp @@ -0,0 +1,849 @@ +#include "scene_map.hpp" + + +extern Game game; +extern Windmill windmill; + +// import des map +extern Map map_village; +extern Map map_interieur_forgeron; + +// import des objets +extern Object chaumiere1; +extern Object panneau1; +extern Object forgeron1; + +//---------------------------------------------------------------------------------------------------- +// CONSTRUCTOR +//---------------------------------------------------------------------------------------------------- +Scene_Map::Scene_Map() +{ + // debug + show_repere = false; + show_coordinates = false; + // histoire + vue_horloge = false; + vue_panneau_moulin = false; + parle_avec_forgeron = false; +} + +//---------------------------------------------------------------------------------------------------- +// LAUNCH +//---------------------------------------------------------------------------------------------------- +void Scene_Map::launch() +{ + time_scene = 0; + + load_map(); + windmill.set_camera(&camera); + + // histoire + // ... +} + + +void Scene_Map::load_map() +{ + // mise a jour de la map pour la scene + windmill.load_map(game.map); + + // creation des bouding box 3D + //delete bbox; + free(bbox); + //bbox = new Bbox3D[game.map->list_object_length]; + bbox = (Bbox3D*) malloc(game.map->list_object_length * sizeof(Bbox3D)); + //if (bbox == NULL) debug_pop("ERROR ptr bbox NULL"); + memset(bbox, 0, game.map->list_object_length * sizeof(Bbox3D)); + + for (int i=0; ilist_object_length; i++) + { + Object* current_object = game.map->object[i]; + Bbox3D* current_bbox = &bbox[i]; + + int nb_poly = (current_object->collision < 0) ? current_object->modele_size : current_object->collision; + if (nb_poly > current_object->modele_size) nb_poly = current_object->modele_size; + + for (int j=0; jmodele[j]; + + for (int k=0; ktype; k++) + { + Point point = windmill.get_point(current_modele, k); + current_bbox->x1 = min(current_bbox->x1, point.x); + current_bbox->y1 = min(current_bbox->y1, point.y); + current_bbox->z1 = min(current_bbox->z1, point.z); + current_bbox->x2 = max(current_bbox->x2, point.x); + current_bbox->y2 = max(current_bbox->y2, point.y); + current_bbox->z2 = max(current_bbox->z2, point.z); + } + } + if (current_object->axe == Z_BILLBOARD) + { + current_bbox->radius = max(current_bbox->y1, current_bbox->y2); + } + + } + + // mise a zero du temps sur la map + time_scene = 0; +} + + +//---------------------------------------------------------------------------------------------------- +// DRAW +//---------------------------------------------------------------------------------------------------- +void Scene_Map::draw() +{ + //ML_clear_vram(); + dclear(C_WHITE); + + windmill.draw(); + + // MAP VILLAGE + if (game.map == &map_village) + { + if (vue_panneau_moulin) + { + //ML_rectangle(34, 15, 95, 50, 0, ML_WHITE, ML_WHITE); + //PrintXY(34, 20, "MOULIN DES", 0); + //PrintXY(52, 30, "RIBES", 0); + //PrintMini(45, 45, "NineStars", 0); + } + } + + // MAP INTERIEUR FORGERON + if (game.map == &map_interieur_forgeron) + { + if (parle_avec_forgeron) + { + //Point point_ancrage = windmill.get_point(&forgeron1.modele, 0); + + //ML_rectangle(50, 10, 118, 54, 1, ML_BLACK, ML_WHITE); + } + } + + if (show_repere) windmill.show_repere(); + if (show_coordinates) windmill.show_coordinates(); + + //ML_display_vram(); + dupdate(); +} + + +//---------------------------------------------------------------------------------------------------- +// UPDATE +//---------------------------------------------------------------------------------------------------- +void Scene_Map::update() +{ + time_scene += 0.02; + + // gestion des touches + /*if (input_trigger(K_EXIT)) + { + scene = EXIT; + return; + } + if (input_trigger(K_MENU)) + { + scene = SCENE_TITLE; + return; + } + if (input_trigger(K_F1)) + { + scene = SCENE_MAP_DEBUG; + return; + } + if (input_trigger(K_F2)) + { + show_repere = !show_repere; + } + if (input_trigger(K_F3)) + { + show_coordinates = !show_coordinates; + }*/ + + // action du joueur sur la map + player_action(); + + // animation des objets sur la map + animation(); + + // mouvements du joueur + if (game.player.can_move) + { + player_move(); + player_turn(); + } + if (game.player.dissociate_camera == false) + { + camera.set(game.player.x, game.player.y, game.player.z + game.player.height, game.player.yaw, game.player.pitch); + } + + //debug_display(id(windmill.object_cursor), 3); + //debug_display(windmill.poly_cursor, 4); +} + + +void Scene_Map::player_action() +{ + // MAP VILLAGE + if (game.map == &map_village) + { + /*if (input_trigger(K_EXE)) + { + if (action_object(object(20))) + { + + if (vue_panneau_moulin) + { + game.player.can_move = true; + game.player.dissociate_camera = false; + windmill.set_camera(&camera); + } else { + game.player.can_move = false; + game.player.dissociate_camera = true; + look(&panneau1, 0, 8, 17, 270, -10); + windmill.set_camera(&camera_look); + } + vue_panneau_moulin = not vue_panneau_moulin; + } + }*/ + + } + + // MAP INTERIEUR FORGERON + if (game.map == &map_interieur_forgeron) + { + /*if (input_trigger(K_EXE)) + { + // interaction avec le forgeron + if (parle_avec_forgeron) + { + parle_avec_forgeron = false; + game.player.can_move = true; + game.player.dissociate_camera = false; + } else { + if (action_object(&forgeron1)) + { + parle_avec_forgeron = true; + game.player.can_move = false; + game.player.dissociate_camera = true; + camera.set(-23, 4, game.player.height, 198, 0); + } + } + }*/ + } +} + + +void Scene_Map::animation() +{ + // MAP VILLAGE + if (game.map == &map_village) + { + object(6)->angle -= 1; + } +} + + + + +void Scene_Map::player_move() +{ + /*///////////// METTRE DANS PLAYER ET RETURN LE FLAG + float new_x = game.player.x; + float new_y = game.player.y; + float new_z = game.player.z; + + // deplacement + float front, side; + input_move(&front, &side); + + // si des touches sont pressees + if (side != 0 or front != 0) + { + game.player.moving = true; + //game.player.translation_speed = min(game.player.translation_speed + 0.25, game.player.translation_speed_max); + if (game.player.translation_speed < game.player.translation_speed_max) + { + game.player.translation_speed += game.player.translation_acceleration; // acceleration + } else { + game.player.translation_speed = game.player.translation_speed_max; + } + // conversion dans le repere monde + float angle_rad = game.player.yaw * 3.1415 / 180.0; + float x = (front * cosf(angle_rad) - side * sinf(angle_rad)) * game.player.translation_speed; + float y = (front * sinf(angle_rad) + side * cosf(angle_rad)) * game.player.translation_speed; + new_x += x; + new_y += y; + } else { + game.player.moving = false; + game.player.translation_speed = 0; + } + + // saut + if (input_press(K_8) and not game.player.jumping) + { + game.player.jump_speed = game.player.jump_speed_max; + game.player.jumping = true; + } else { + game.player.jump_speed -= 0.981; // gravite + } + new_z += game.player.jump_speed; + + // collision + flag = collision(&new_x, &new_y, &new_z); + + // contact avec le sol ou un objet + if (flag.type == COLLISION_GROUND or flag.type == COLLISION_ON) + { + game.player.jumping = false; + game.player.jump_speed = 0; + } + + // hors terrain + if (flag.type == COLLISION_BOUND) + { + debug_display("trop loin", 2); + } + + game.player.x = new_x; + game.player.y = new_y; + game.player.z = new_z; + */ +} + + +void Scene_Map::player_turn() +{/* + float yaw = 0; + float pitch = 0; + + if (input_press(K_RIGHT)) yaw = -1; + if (input_press(K_LEFT)) yaw = 1; + if (input_press(K_DOWN)) pitch = -0.5; + if (input_press(K_UP)) pitch = 0.5; + + if (yaw != 0 or pitch != 0) + { + game.player.turning = true; + if (game.player.rotation_speed < game.player.rotation_speed_max) + { + game.player.rotation_speed += float(game.player.rotation_speed_max / 10.0); + } + } else { + game.player.turning = false; + game.player.rotation_speed = 0; + } + + yaw = game.player.yaw + yaw * game.player.rotation_speed; + pitch = game.player.pitch + pitch * game.player.rotation_speed; + if (yaw < 0) yaw += 360; + if (yaw >= 360) yaw -= 360; + if (pitch > 90) pitch = 90; + if (pitch < -90) pitch = -90; + + game.player.yaw = yaw; + game.player.pitch = pitch; + */ +} + + +//----------------------------------------------------------------------------- +// COLLISION +// renvoie le type de la derniere collision detectee +// 0 rien +// 1 sol +// 2 cote objet +// 3 dessus objet +// 4 z_billboard +// 5 hors terrain +//----------------------------------------------------------------------------- +Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z) +{ + Collision_flag flag; + + float belly = game.player.belly; + float total_height = game.player.total_height; + + flag.type = COLLISION_NONE; + flag.object = NULL; + + if (*new_z <= 0) + { + *new_z = 0; + flag.type = COLLISION_GROUND; + } + + for (int i = 0; ilist_object_length; i++) + { + Object* current_object = game.map->object[i]; + + // si une bbox a ete cree pour l objet + if (current_object->collision != 0) + { + Bbox3D* current_bbox = &bbox[i]; + + float cosinus, sinus; + float player_x, player_y, player_z; + float temp_new_x, temp_new_y, temp_new_z; + + // si objet.axe != N + if (current_object->axe == Z) + { + float angle = 3.1415 * current_object->angle / 180.0; + cosinus = cosf(angle); + sinus = sinf(angle); + + player_x = cosinus * (game.player.x-current_object->x) + sinus * (game.player.y-current_object->y); + player_y = - sinus * (game.player.x-current_object->x) + cosinus * (game.player.y-current_object->y); + player_z = game.player.z - current_object->z; + + temp_new_x = cosinus * (*new_x-current_object->x) + sinus * (*new_y-current_object->y); + temp_new_y = - sinus * (*new_x-current_object->x) + cosinus * (*new_y-current_object->y); + temp_new_z = *new_z - current_object->z; + } else { + cosinus = 1; + sinus = 0; + + player_x = game.player.x - current_object->x; + player_y = game.player.y - current_object->y; + player_z = game.player.z - current_object->z; + + temp_new_x = *new_x - current_object->x; + temp_new_y = *new_y - current_object->y; + temp_new_z = *new_z - current_object->z; + } + + if (temp_new_z > current_bbox->z2) + { + // player au dessus + + // si je mets rien ici, on pourra pas sauter sur une caisse... + } else if (temp_new_z + total_height < current_bbox->z1) + { + // player en dessous + + } else { + // détermine si INT ou EXT + //if (game.player.x > current_bbox->x1 and game.player.x < current_bbox->x2 and + // game.player.y > current_bbox->y1 and game.player.y < current_bbox->y2) + if (current_object->collision < 0) + { + // si player a l interieur de l objet + if (temp_new_x - belly < current_bbox->x1) + { + temp_new_x = current_bbox->x1 + belly; + } + if (temp_new_x + belly > current_bbox->x2) + { + temp_new_x = current_bbox->x2 - belly; + } + if (temp_new_y - belly < current_bbox->y1) + { + temp_new_y = current_bbox->y1 + belly; + } + if (temp_new_y + belly > current_bbox->y2) + { + temp_new_y = current_bbox->y2 - belly; + } + *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; + *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; + + if (flag.type <= COLLISION_WALL) + { + flag.type = COLLISION_WALL; + flag.object = current_object; + } + } else { + if (current_object->axe == Z_BILLBOARD) + { + bool inside_after = belly < current_bbox->radius; + if (inside_after) + { + //debug_pop("collsiosn"); + if (flag.type <= COLLISION_CARA) + { + flag.type = COLLISION_CARA; + flag.object = current_object; + } + } + } else { + bool inside_after = (temp_new_x + belly > current_bbox->x1 and temp_new_x - belly < current_bbox->x2 and + temp_new_y + belly > current_bbox->y1 and temp_new_y - belly < current_bbox->y2); + // si player a l exterieur de l objet + if (inside_after) + { + // player rentre dans objet par le haut + if (player_z >= current_bbox->z2 and temp_new_z < current_bbox->z2) + { + temp_new_z = current_object->z + current_bbox->z2; + *new_z = temp_new_z; + if (flag.type <= COLLISION_ON) + { + flag.type = COLLISION_ON; + flag.object = current_object; + } + } else { + // si on rentre dans l'objet + if (player_x < current_bbox->x1) + { + temp_new_x = current_bbox->x1 - belly; + } + if (player_x > current_bbox->x2) // modifier par un else ? + { + temp_new_x = current_bbox->x2 + belly; + } + if (player_y < current_bbox->y1) + { + temp_new_y = current_bbox->y1 - belly; + } + if (player_y > current_bbox->y2) + { + temp_new_y = current_bbox->y2 + belly; + } + // transformation inverse + *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; + *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; + + if (flag.type <= COLLISION_WALL) + { + flag.type = COLLISION_WALL; + flag.object = current_object; + } + } + } + } + } + } + } + } + + + if (*new_x * *new_x + *new_y * *new_y > MAP_EXTERIOR_LIMIT * MAP_EXTERIOR_LIMIT) + { + flag.type = COLLISION_BOUND; + *new_x = game.player.x; + *new_y = game.player.y; + } + + return flag; +} +/*Collision_flag Scene_Map::collision(float* new_x, float* new_y, float* new_z) +{ + Collision_flag flag; + + float belly = game.player.belly; + float total_height = game.player.total_height; + + flag.type = COLLISION_NONE; + flag.object = NULL; + + if (*new_z <= 0) + { + *new_z = 0; + flag.type = COLLISION_GROUND; + } + + for (int i = 0; ilist_object_length; i++) + { + Object* current_object = game.map->object[i]; + + // si une bbox a ete cree pour l objet + if (current_object->for_collision != 0) + { + Bbox3D* current_bbox = &bbox[i]; + + float cosinus, sinus; + float player_x, player_y, player_z; + float temp_new_x, temp_new_y, temp_new_z; + + // si objet.axe != N + if (current_object->axe == Z) + { + float angle = 3.1415 * current_object->angle / 180.0; + cosinus = cosf(angle); + sinus = sinf(angle); + + player_x = cosinus * (game.player.x-current_object->x) + sinus * (game.player.y-current_object->y); + player_y = - sinus * (game.player.x-current_object->x) + cosinus * (game.player.y-current_object->y); + player_z = game.player.z - current_object->z; + + temp_new_x = cosinus * (*new_x-current_object->x) + sinus * (*new_y-current_object->y); + temp_new_y = - sinus * (*new_x-current_object->x) + cosinus * (*new_y-current_object->y); + temp_new_z = *new_z - current_object->z; + } else { + cosinus = 1; + sinus = 0; + + player_x = game.player.x - current_object->x; + player_y = game.player.y - current_object->y; + player_z = game.player.z - current_object->z; + + temp_new_x = *new_x - current_object->x; + temp_new_y = *new_y - current_object->y; + temp_new_z = *new_z - current_object->z; + } + + if (temp_new_z > current_bbox->z2) + { + // player au dessus + + // si je mets rien ici, on pourra pas sauter sur une caisse... + } else if (temp_new_z + total_height < current_bbox->z1) + { + // player en dessous + + } else { + // détermine si INT ou EXT + //if (game.player.x > current_bbox->x1 and game.player.x < current_bbox->x2 and + // game.player.y > current_bbox->y1 and game.player.y < current_bbox->y2) + if (current_object->type_collision == OUT) + { + // si player a l interieur de l objet + if (temp_new_x - belly < current_bbox->x1) + { + temp_new_x = current_bbox->x1 + belly; + } + if (temp_new_x + belly > current_bbox->x2) + { + temp_new_x = current_bbox->x2 - belly; + } + if (temp_new_y - belly < current_bbox->y1) + { + temp_new_y = current_bbox->y1 + belly; + } + if (temp_new_y + belly > current_bbox->y2) + { + temp_new_y = current_bbox->y2 - belly; + } + *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; + *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; + + if (flag.type <= COLLISION_WALL) + { + flag.type = COLLISION_WALL; + flag.object = current_object; + } + } + + if (current_object->type_collision == IN) + { + if (current_object->axe == Z_BILLBOARD) + { + bool inside_after = belly < current_bbox->radius; + if (inside_after) + { + //debug_pop("collsiosn"); + if (flag.type <= COLLISION_CARA) + { + flag.type = COLLISION_CARA; + flag.object = current_object; + } + } + } else { + bool inside_after = (temp_new_x + belly > current_bbox->x1 and temp_new_x - belly < current_bbox->x2 and + temp_new_y + belly > current_bbox->y1 and temp_new_y - belly < current_bbox->y2); + // si player a l exterieur de l objet + if (inside_after) + { + // player rentre dans objet par le haut + if (player_z >= current_bbox->z2 and temp_new_z < current_bbox->z2) + { + temp_new_z = current_object->z + current_bbox->z2; + *new_z = temp_new_z; + if (flag.type <= COLLISION_ON) + { + flag.type = COLLISION_ON; + flag.object = current_object; + } + } else { + // si on rentre dans l'objet + if (player_x < current_bbox->x1) + { + temp_new_x = current_bbox->x1 - belly; + } + if (player_x > current_bbox->x2) // modifier par un else ? + { + temp_new_x = current_bbox->x2 + belly; + } + if (player_y < current_bbox->y1) + { + temp_new_y = current_bbox->y1 - belly; + } + if (player_y > current_bbox->y2) + { + temp_new_y = current_bbox->y2 + belly; + } + // transformation inverse + *new_x = cosinus * temp_new_x - sinus * temp_new_y + current_object->x; + *new_y = sinus * temp_new_x + cosinus * temp_new_y + current_object->y; + + if (flag.type <= COLLISION_WALL) + { + flag.type = COLLISION_WALL; + flag.object = current_object; + } + } + } + } + } + } + } + } + + + if (*new_x * *new_x + *new_y * *new_y > MAP_EXTERIOR_LIMIT * MAP_EXTERIOR_LIMIT) + { + flag.type = COLLISION_BOUND; + *new_x = game.player.x; + *new_y = game.player.y; + } + + return flag; +}*/ + + +void Scene_Map::look(Object* object, float x, float y, float z, float yaw, float pitch) +{ + Vertex vertex; + int cosinus, sinus; + + vertex.set_xyz(x, y, z); + windmill.compute_object_angle(object, &cosinus, &sinus); + windmill.transform_model_to_world(&vertex, 1, object, cosinus, sinus); + + camera_look.x = vertex.x; + camera_look.y = vertex.y; + camera_look.z = vertex.z; + camera_look.yaw = PI * (object->angle + yaw) / DEG; + camera_look.pitch = to_rad(pitch); +} + + +void Scene_Map::lerp_camera(Camera camera_start, Camera camera_end, float t) +{ + camera_temp.x = (1-t) * camera_start.x + t * camera_end.x; + camera_temp.y = (1-t) * camera_start.y + t * camera_end.y; + camera_temp.z = (1-t) * camera_start.z + t * camera_end.z; + camera_temp.yaw = (1-t) * camera_start.yaw + t * camera_end.yaw; + camera_temp.pitch = (1-t) * camera_start.pitch + t * camera_end.pitch; +} + + +Object* Scene_Map::object(int id) +{ + if (id < 0 or id >= game.map->list_object_length) + { + //debug_pop("ERROR id out of range"); + return NULL; + } + return game.map->object[id]; +} + + +int Scene_Map::id(Object* object) +{ + if (object == NULL) return -1; + for (int i = 0; ilist_object_length; i++) + { + if (game.map->object[i] == object) + { + return i; + } + } + //debug_pop("ERROR object not found"); + return -1; +} + + +bool Scene_Map::action_object(Object* object, int poly_id) +{ + if (look_object(object, poly_id) == false) return false; + + Point center_poly = windmill.get_center_poly(&object->modele[poly_id]); + + return action_object(object, center_poly.x, center_poly.y, center_poly.z); +} + + +bool Scene_Map::action_object(Object* object, float x, float y, float z) +{ + Vertex vertex; + int cosinus, sinus; + + vertex.set_xyz(x, y, z); + windmill.compute_object_angle(object, &cosinus, &sinus); + windmill.transform_model_to_world(&vertex, 1, object, cosinus, sinus); + + float dx = vertex.x - game.player.x; + float dy = vertex.y - game.player.y; + float dz = vertex.z - game.player.z; + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + if (dz < 0) dz = -dz; + + return (dx <= game.player.action_distance and dy <= game.player.action_distance); +} + + +bool Scene_Map::look_object(Object* object, int poly_id) +{ + if (poly_id == -1) + { + return (object == windmill.object_cursor); + } else { + return (object == windmill.object_cursor and poly_id == windmill.poly_cursor); + } + +} + + +//---------------------------------------------------------------------------------------------------- +// TERMINATE +//---------------------------------------------------------------------------------------------------- +void Scene_Map::terminate() +{ + +} +//---------------------------------------------------------------------------------------------------- +// DESTRUCTOR +//---------------------------------------------------------------------------------------------------- +Scene_Map::~Scene_Map() +{ + // rien +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/scene_map.hpp b/src/scene_map.hpp new file mode 100644 index 0000000..60aed71 --- /dev/null +++ b/src/scene_map.hpp @@ -0,0 +1,101 @@ +#ifndef DEF_SCENE_MAP +#define DEF_SCENE_MAP + +extern "C" +{ + #include + #include +} +#include "windmill.hpp" +#include "game.hpp" + + +#define EXIT 0 +#define SCENE_TITLE 1 +#define SCENE_MAP 2 +#define SCENE_MAP_DEBUG 3 + +#define PI 3.1415 +#define DEG 180.0 + +#define MAP_EXTERIOR_LIMIT 1000 +#define COLLISION_NONE 0 +#define COLLISION_GROUND 1 +#define COLLISION_WALL 2 +#define COLLISION_ON 3 +#define COLLISION_CARA 4 +#define COLLISION_BOUND 5 + +struct Collision_flag +{ + int type; + Object* object; +}; + + +struct Bbox3D +{ + short x1, y1, z1; + short x2, y2, z2; + short radius; +}; + +struct Location +{ + float x, y, z; + float yaw, pitch; +}; + + +class Scene_Map +{ +public: + Scene_Map(); + void launch(); + void update(); + void draw(); + void animation(); + void player_action(); + void load_map(); + //Object* object(int id); + void terminate(); + ~Scene_Map(); + + void player_move(); + void player_turn(); + Collision_flag collision(float* new_x, float* new_y, float* new_z); + + void look(Object* object, float x, float y, float z, float yaw, float pitch); + void lerp_camera(Camera camera_start, Camera camera_end, float t); + + // renvoie un pointeur vers l objet dont l id est connu + Object* object(int id); + // renvoie l id d un objet connu + int id(Object* object); + // retourne true si le joueur + bool action_object(Object* object, int poly_id = -1); + // retourne true si le joueur est proche du point (x,y,z) dans le repere de l'objet + bool action_object(Object* object, float x, float y, float z); + // retourne true le joueur regarde l objet [et le poly indique] + bool look_object(Object* object, int poly_id = -1); + + Camera camera; + float time_scene; + + // collision + Bbox3D* bbox; + Collision_flag flag; + + // histoire + bool show_repere; + bool show_coordinates; + + Camera camera_look; // camera ou regarder + Camera camera_temp; // camera temporaire pour les transitions + bool vue_horloge; + bool vue_panneau_moulin; + bool parle_avec_forgeron; + Location position_pancarte_entrepot; +}; + +#endif diff --git a/src/windmill.cpp b/src/windmill.cpp new file mode 100644 index 0000000..3b2a836 --- /dev/null +++ b/src/windmill.cpp @@ -0,0 +1,1788 @@ +//---------------------------------------------------------------------------------------------------- +// +// WINDMILL +// +// version : 2.0 +// Moteur de rendu 3D base sur la methode de rasterisation avec buffer de profondeur +// +// Cree par Olivier Lanneau, alias NineStars +// Planet-casio.fr +// +//---------------------------------------------------------------------------------------------------- + + +#include "windmill.hpp" + +//const Texture tex_black = {}; +//const Texture tex_white = {}; +extern Texture tex_white; +extern Texture tex_light; +extern Texture tex_dark; +extern Texture tex_black; + + +//---------------------------------------------------------------------------------------------------- +// INITIALISATION +//---------------------------------------------------------------------------------------------------- +Windmill::Windmill() +{ + camera2 = NULL; + map = NULL; + object = NULL; + z_buffer = NULL; + set_viewport(0, 0, 128, 64); + + nb_object_on_screen = 0; + temp_object_cursor = NULL; + temp_poly_cursor = -1; +} + + +void Windmill::set_camera(Camera* _camera) +{ + camera2 = _camera; +} + + +void Windmill::set_viewport(int viewport_x1, int viewport_y1, int viewport_x2, int viewport_y2) +{ + viewport.x1 = max(0, viewport_x1); + viewport.y1 = max(0, viewport_y1); + viewport.x2 = min(viewport_x2, DWIDTH); + viewport.y2 = min(viewport_y2, DHEIGHT); + + //if (z_buffer != NULL) free(z_buffer); + free(z_buffer); + shift_x = (viewport.x1 + viewport.x2) / 2; + shift_y = (viewport.y1 + viewport.y2) / 2; + + z_buffer_size = (viewport.x2 - viewport.x1) * (viewport.y2 - viewport.y1); + z_buffer = (unsigned short*) calloc(z_buffer_size, 2); + //if (z_buffer == NULL) debug_pop("ERROR ptr z_buffer NULL"); + z_buffer_width = viewport.x2 - viewport.x1; + z_buffer_offset = - viewport.x1 - viewport.y1 * DWIDTH; + clear_z_buffer(); + + cursor_x = shift_x; + cursor_y = shift_y; +} + + +void Windmill::load_map(Map* _map) +{ + loading = true; + + if (map != _map) + { + // attribution de la map + map = _map; + + // enregistrement des objets de la map dans un tableau + // ceci permet de trier les objets pour les afficher du plus + // pres au plus loin + list_object_length = map->list_object_length; + //delete[] object; + free(object); + //object = new Object* [list_object_length]; + object = (Object**) malloc(list_object_length * sizeof(Object)); + //if (object == NULL) debug_pop("ERROR ptr object NULL"); + for (int i = 0; iobject[i]; + } + + // generation des spheres englobantes + // pour chaque objet + for (int i = 0; ilist_object_length; i++) + { + Object* current_object = map->object[i]; + int nb_point = 0; + int center_x = 0; + int center_y = 0; + int center_z = 0; + + // pour chaque poly + for (int j = 0; jmodele_size; j++) + { + const Modele* current_poly = ¤t_object->modele[j]; + + // pour chaque point + for (int k = 0; ktype; k++) + { + Point point = get_point(current_poly, k); + center_x += point.x; + center_y += point.y; + center_z += point.z; + + nb_point++; + } + } + // barycentre + center_x /= nb_point; + center_y /= nb_point; + center_z /= nb_point; + + // recherche du point le plus eloigne du centre + int radius_max = 0; + for (int j = 0; jmodele_size; j++) + { + const Modele* current_poly = ¤t_object->modele[j]; + for (int k = 0; ktype; k++) + { + Point point = get_point(current_poly, k); + int dx = point.x - center_x; + int dy = point.y - center_y; + int dz = point.z - center_z; + int radius = dx*dx + dy*dy + dz*dz; + //int rr = sqrtf(radius); + if (radius > radius_max) + { + radius_max = radius; + } + } + } + radius_max = sqrtf(radius_max) + 1; + + current_object->sphere.x = center_x; + current_object->sphere.y = center_y; + current_object->sphere.z = center_z; + current_object->sphere.radius = radius_max; + } + } + + loading = false; +} + + + + + +//---------------------------------------------------------------------------------------------------- +// DESSIN +//---------------------------------------------------------------------------------------------------- +void Windmill::draw() +{ + // quitte si pas de camera, de map, d objet ou de z_buffer + if(camera2 == NULL or map == NULL or object == NULL or z_buffer == NULL) return; + + // mets a jour les variables de la camera + camera2->update(); + + // cree une camera temporaire pour eviter les problemes de desynchronisation + copy_camera(); + + // fonction principale, l'ordre d'appel des fonctions suivantes est important + clear_z_buffer(); + + // trie les objets pour optimiser l affichage + sort_object(); + + // affiche le trait d'horizon + if (map->horizon) draw_horizon(); + + // affiche le sol + if (map->ground) draw_ground(); + + // affiche les objets de la scene + draw_objects(); + + // post traitement pour afficher les angles vifs + draw_post_treatment(); + + // affiche le corps du personnage + draw_body(); + + // affiche des informations + //show_fps(); + //show_coordinates(); + //show_repere(); +} + + +void Windmill::draw_horizon() +{ + Vertex horizon; + char* vram = get_vram_address(); + int distance = 1000; + int hx = camera.x + distance * camera.cos_yaw; + int hy = camera.y + distance * camera.sin_yaw; + + horizon.set_xyz(hx, hy, 0); + + transform_world_to_camera(&horizon, 1); + transform_camera_to_screen(&horizon, 1); + if (inside_viewport(horizon.x, horizon.y)) + { + dline(viewport.x1, horizon.y, viewport.x2, horizon.y, C_BLACK); + //ML_line(viewport.x1, horizon.y, viewport.x2, horizon.y, ML_BLACK); + } +} + + +void Windmill::draw_ground() +{ + Vertex ground; + char* vram = get_vram_address(); + unsigned char mask; + int distance = 50; + int esp = 20; + int nb = 6; + int nb2 = nb * nb; + float cx = camera.x + distance * camera.cos_yaw; + float cy = camera.y + distance * camera.sin_yaw; + int dx = int(cx) - int(cx)%esp; + int dy = int(cy) - int(cy)%esp; + + for (int i=-nb; i 0) + { + transform_camera_to_screen(&ground, 1); + if (inside_viewport(ground.x, ground.y) == true) + { + mask = 128 >> (ground.x & 7); + vram[(ground.y << 4) + (ground.x>>3)] |= mask; + } + } + } + } + } +} + + +void Windmill::draw_objects() +{ + nb_object_on_screen = 0; + temp_object_cursor = NULL; + temp_poly_cursor = -1; + + Vertex vertex[10]; + int vertex_length; + int width, height; + int cosinus, sinus; + + for(i=0; ilist_object_length; i++) + { + //Object* current_object = map->object[i]; + Object* current_object = object[i]; + + if (current_object->hidden == false) + { + // angle de l objet + compute_object_angle(current_object, &cosinus, &sinus); + + // transforme la sphere dans le repere monde + Sphere current_sphere = transform_sphere_to_world(¤t_object->sphere, current_object, cosinus, sinus); + + // verifie si la sphere englobante est dans le champs de vision de la camera + if (sphere_in_cone(¤t_sphere)) + { + temp_nb_object_on_screen ++; + current_object->on_screen = true; + current_object->distance_to_camera = current_sphere.z; + + for(j=0; jmodele_size; j++) + { + const Modele* current_poly = ¤t_object->modele[j]; + + // creation des vertex a partir du poly + extract_vertex_from_poly(current_poly, vertex, &vertex_length, &width, &height); + + // calcul des coordonnees dans le repère monde apres rotation et translation de l objet + transform_model_to_world(vertex, vertex_length, current_object, cosinus, sinus); + + // calcul des coordonnees dans le repère camera apres rotation et translation de la camera + transform_world_to_camera(vertex, vertex_length); + + // verifie si au moins 1 point peut etre visible + if (fast_check(vertex, vertex_length)) + { + // calcul de l'aire du rectangle pour connaitre sa face visible + int visible = visible_face(&vertex[0], &vertex[1], &vertex[2]); + + // choisi la texture visible + const Texture* texture; + texture = (visible == FRONT) ? current_poly->texture_front : current_poly->texture_back; + + // si le rectangle est visible + if (texture != NULL) + { + // si le rectangle a une texture + if (texture != &tex_black && texture != &tex_white) + { + texture_coordinates(current_poly, vertex, texture, visible, width, height); + } + + // tronque le polygon devant le plan avant de la camera + clip_depth(vertex, &vertex_length); + + // calcul des coordonnes apres perspective et decalage au centre de l ecran + transform_camera_to_screen(vertex, vertex_length); + + // tronque le polygon sur les bords de l ecran + clip_viewport(vertex, &vertex_length); + + // calcul des coordonnees de profondeur + transform_camera_to_screen2(vertex, vertex_length); + + // affiche les triangles + if (visible == FRONT) + { + for (int k = 1; k1; k--) + { + render_triangle(&vertex[0], &vertex[k], &vertex[k-1], texture); + } + } + } + } + } + } else { + current_object->on_screen = false; + } + } + } + + nb_object_on_screen = temp_nb_object_on_screen; + object_cursor = temp_object_cursor; + poly_cursor = temp_poly_cursor; +} + + +void Windmill::draw_post_treatment() +{ + char* vram = get_vram_address(); + unsigned char mask; + int current, right, bottom, left; + + for (int y = viewport.y1; y> ((x+1) & 7); + vram[address<<3] |= mask; + + //ML_pixel(x+1, y, ML_BLACK); + } + if (bottom < MAX_DEPTH_Z_BUFFER) + { + dpixel(x, y+1, C_BLACK); + //ML_pixel(x, y+1, ML_BLACK); + } + } else { + if (right == MAX_DEPTH_Z_BUFFER or bottom == MAX_DEPTH_Z_BUFFER) + { + dpixel(x, y+1, C_BLACK); + //ML_pixel(x, y, ML_BLACK); + } + } + } + + } // 21 fps 21,5 fps*/ + + /*left = z_buffer[0]; + for (int i = 1; i> (i & 7); + vram[(i - z_buffer_offset)>>3] |= mask; + } + } else { + if (left < MAX_DEPTH_Z_BUFFER) + { + mask = 128 >> ((i-1) & 7); + vram[(i - 1 - z_buffer_offset)>>3] |= mask; + + } + } + } + // sans rien 28 fps + // avec le i+1 : 24 fps + // avec le i : 25 fps + // calculer left = Z_buffer[i-1] dans if : 24 fps + // avec les deux cote : 24 fps ! */ + + bool flag = false; + for (int i = 0; i> ((i-2) & 7); + vram[(i - 2 - z_buffer_offset)>>3] |= mask; + flag = false; + } else { + // l objet commencait en fait 1 pixel a gauche + mask = 128 >> ((i-1) & 7); + vram[(i - 1 - z_buffer_offset)>>3] |= mask; + flag = false; + } + } + } else { + if (flag == false) + { + if (z_buffer[i-1] == MAX_DEPTH_Z_BUFFER) + { + // il y avait rien juste a gauche + mask = 128 >> (i & 7); + vram[(i - z_buffer_offset)>>3] |= mask; + flag = true; + } else { + // l objet commencait en fait 1 pixel a gauche + mask = 128 >> ((i-1) & 7); + vram[(i - 1 - z_buffer_offset)>>3] |= mask; + flag = true; + } + } + } + } // 24 fps + // avec astuce +=2 : 25 fps + + /*bool flag = false; + char i_mod_8; + for (int i = 0; i> i_mod_8;//((i-1) & 7); + flag = false; + } + } else { + if (flag == false) + { + mask |= 128 >> i_mod_8; + flag = true; + } + } + if (i_mod_8 == 7) + { + //if (mask > 0) + vram[i>>3] |= mask; + mask = 0; + } + }*/ +} + + +void Windmill::draw_body() +{ + /*int x = camera.x; + int y = camera.y; + int z = camera.z; + + Vertex v0, v1, v2, v3; + set_vertex_xyz() + METTRE DIRECT LES VERTEX DANS LE REPERE SCREEN PUIS RENDER... +*/ +} + + + + + +//---------------------------------------------------------------------------------------------------- +// TRANSFORMATION 3D +//---------------------------------------------------------------------------------------------------- +void Windmill::transform_model_to_world(Vertex vertex[], int vertex_length, Object* object, int cosinus, int sinus) +{ + for (int k = 0; kaxe == N) + { + vertex[k].x = vertex_x + object->x; + vertex[k].y = vertex_y + object->y; + vertex[k].z = vertex_z + object->z; + } + if (object->axe == X) + { + vertex[k].x = vertex_x + object->x; + vertex[k].y = ((vertex_y * cosinus - vertex_z * sinus) >> 10) + object->y; + vertex[k].z = ((vertex_y * sinus + vertex_z * cosinus) >> 10) + object->z; + } + if (object->axe == Y) + { + vertex[k].x = ((vertex_x * cosinus - vertex_z * sinus) >> 10) + object->x; + vertex[k].y = vertex_y + object->y; + vertex[k].z = ((vertex_x * sinus + vertex_z * cosinus) >> 10) + object->z; + } + if (object->axe == Z or object->axe == Z_BILLBOARD) + { + vertex[k].x = ((vertex_x * cosinus - vertex_y * sinus) >> 10) + object->x; + vertex[k].y = ((vertex_x * sinus + vertex_y * cosinus) >> 10) + object->y; + vertex[k].z = vertex_z + object->z; + } + + } +} + + +void Windmill::transform_world_to_camera(Vertex vertex[], int vertex_length) +{ + for (int k = 0; kz_normalized = (1<<15) * (vertex->z * camera.far - SCALE_AI * camera.far * camera.near) / (vertex->z * (camera.far - camera.near)); + // precalcul de 1/z + vertex[k].z = (1<<20) / vertex[k].z; + } +} + + + + + +//---------------------------------------------------------------------------------------------------- +// TEST VISIBILITE +//---------------------------------------------------------------------------------------------------- +bool Windmill::fast_check(Vertex vertex[], int vertex_length) +{ + int near = camera.near * SCALE_AI; + int far = camera.far * SCALE_AI; + + for (int i = 0; i= near and vertex[i].z < far) return true; + } + + return false; +} + + +bool Windmill::inside_viewport(int x, int y) +{ + return (x < viewport.x2 and y >= viewport.y1 and x >= viewport.x1 and y < viewport.y2); +} + + +int Windmill::visible_face(Vertex* a, Vertex* b, Vertex* c) +{ + int nx = ((b->y - a->y) * (c->z - a->z) - (b->z - a->z) * (c->y - a->y)) >> 15; + int ny = ((b->z - a->z) * (c->x - a->x) - (b->x - a->x) * (c->z - a->z)) >> 15; + int nz = ((b->x - a->x) * (c->y - a->y) - (b->y - a->y) * (c->x - a->x)) >> 15; + return (nx*a->x + ny*a->y + nz*a->z > 0) ? BACK : FRONT; +} + + + +// Sutherland–Hodgman algorithm +void Windmill::clip_depth(Vertex vertex_input[], int* vertex_input_length) +{ + Vertex vertex_temp; + Vertex vertex_output[10]; + int vertex_output_length = 0; + + int S = *vertex_input_length-1; + + for (int E = 0; E<*vertex_input_length; E++) + { + if (clip_depth_inside_edge(&vertex_input[E]) == true) + { + if (clip_depth_inside_edge(&vertex_input[S]) == false) + { + clip_depth_edge(&vertex_input[E], &vertex_input[S], &vertex_temp); + copy_vertex(&vertex_temp, &vertex_output[vertex_output_length]); + vertex_output_length += 1; + } + copy_vertex(&vertex_input[E], &vertex_output[vertex_output_length]); + vertex_output_length += 1; + + } else if (clip_depth_inside_edge(&vertex_input[S]) == true) + { + clip_depth_edge(&vertex_input[S], &vertex_input[E], &vertex_temp); + copy_vertex(&vertex_temp, &vertex_output[vertex_output_length]); + vertex_output_length += 1; + } + S = E; + + } + + *vertex_input_length = vertex_output_length; + for (int i = 0; i<*vertex_input_length; i++) + { + copy_vertex(&vertex_output[i], &vertex_input[i]); + } +} + + +void Windmill::clip_depth_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set) +{ + int near, x_near, y_near, z_near, w_near, h_near; + float t; + + near = camera.near * SCALE_AI; + t = float(near - vertex_in->z) / float(vertex_out->z - vertex_in->z); + + x_near = (vertex_out->x - vertex_in->x) * t + vertex_in->x; + y_near = (vertex_out->y - vertex_in->y) * t + vertex_in->y; + z_near = near; + + w_near = (vertex_out->w - vertex_in->w) * t + vertex_in->w; + h_near = (vertex_out->h - vertex_in->h) * t + vertex_in->h; + + vertex_set->set_xyz(x_near, y_near, z_near); + vertex_set->set_wh(w_near, h_near); +} + + +bool Windmill::clip_depth_inside_edge(Vertex* vertex) +{ + return (vertex->z >= camera.near * SCALE_AI) ? true : false; +} + + +// Sutherland–Hodgman algorithm +void Windmill::clip_viewport(Vertex vertex_input[], int* vertex_input_length) +{ + Vertex vertex_temp; + + Vertex vertex_output[10]; + int vertex_output_length = *vertex_input_length; + + for (int i = 0; i<*vertex_input_length; i++) + { + copy_vertex(&vertex_input[i], &vertex_output[i]); + } + + for (int edge = 0; edge < 4; edge++) + { + for (int i = 0; ix) / float(vertex_out->x - vertex_in->x); + x_set = viewport.x2-1; + y_set = (vertex_out->y - vertex_in->y) * t + vertex_in->y; + } + if (edge == 1) + { + t = float(viewport.y1 - vertex_in->y) / float(vertex_out->y - vertex_in->y); + x_set = (vertex_out->x - vertex_in->x) * t + vertex_in->x; + y_set = viewport.y1; + } + if (edge == 2) + { + t = float(viewport.x1 - vertex_in->x) / float(vertex_out->x - vertex_in->x); + x_set = viewport.x1; + y_set = (vertex_out->y - vertex_in->y) * t + vertex_in->y; + } + if (edge == 3) + { + t = float(viewport.y2 - 1 - vertex_in->y) / float(vertex_out->y - vertex_in->y); + x_set = (vertex_out->x - vertex_in->x) * t + vertex_in->x; + y_set = viewport.y2-1; + } + + z_set = 0.5 + float(1) / (float(1-t)/float(vertex_in->z) + float(t)/float(vertex_out->z)); + w_set = z_set * ( (1.0-t) * vertex_in->w / float(vertex_in->z) + t * vertex_out->w / float(vertex_out->z) ); + h_set = z_set * ( (1.0-t) * vertex_in->h / float(vertex_in->z) + t * vertex_out->h / float(vertex_out->z) ); + + + vertex_set->set_xyz(x_set, y_set, z_set); + vertex_set->set_wh(w_set, h_set); +} + + +bool Windmill::clip_viewport_inside_edge(Vertex* vertex, int edge) +{ + // 0 : RIGHT 1 : UP 2: LEFT 3 : DOWN + if (edge == 0 and vertex->x < viewport.x2-1) return true; + if (edge == 1 and vertex->y > viewport.y1) return true; + if (edge == 2 and vertex->x > viewport.x1) return true; + if (edge == 3 and vertex->y < viewport.y2-1) return true; + + return false; +} + + + + + +//---------------------------------------------------------------------------------------------------- +// DESSIN DES TRIANGLES +//---------------------------------------------------------------------------------------------------- +void Windmill::render_triangle(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture *texture)//, bool billboard) +{ + //render_triangle_black(vertexA, vertexB, vertexC); + if (texture == NULL) return; + if (texture == &tex_black) + { + render_triangle_black(vertexA, vertexB, vertexC); + } + else if (texture == &tex_white) + { + render_triangle_white(vertexA, vertexB, vertexC); + } + else if (texture->transparent == true) + { + render_triangle_transparent(vertexA, vertexB, vertexC, texture); + } + else + { + render_triangle_texture(vertexA, vertexB, vertexC, texture); + } +} + + +void Windmill::render_triangle_texture(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture* texture) +{ + // calcul du rectangle circonscrit au triangle + int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x))); + int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x))); + int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y))); + int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y))); + + // calcul de l'aire du triangle + int area = edge(vertexA, vertexB, vertexC); + // determine si la taille du triangle est trop petite + if (area <= MIN_AREA_CLIP) return; + + // pre-calcul des coordonnees de la texture + int w0 = vertexA->w * vertexA->z; int h0 = vertexA->h * vertexA->z; + int w1 = vertexB->w * vertexB->z; int h1 = vertexB->h * vertexB->z; + int w2 = vertexC->w * vertexC->z; int h2 = vertexC->h * vertexC->z; + + // calcul des produits vectoriels + int u0_start = edge_start(vertexB, vertexC, min_x, min_y); + int u0_step_x = edge_step_x(vertexB, vertexC); + int u0_step_y = edge_step_y(vertexB, vertexC); + int u1_start = edge_start(vertexC, vertexA, min_x, min_y); + int u1_step_x = edge_step_x(vertexC, vertexA); + int u1_step_y = edge_step_y(vertexC, vertexA); + int u2_start = edge_start(vertexA, vertexB, min_x, min_y); + int u2_step_x = edge_step_x(vertexA, vertexB); + int u2_step_y = edge_step_y(vertexA, vertexB); + + int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area; + int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area; + int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area; + + int z_div_start = u0_start * vertexA->z + u1_start * vertexB->z + u2_start * vertexC->z; + int z_div_step_x = u0_step_x * vertexA->z + u1_step_x * vertexB->z + u2_step_x * vertexC->z; + int z_div_step_y = u0_step_y * vertexA->z + u1_step_y * vertexB->z + u2_step_y * vertexC->z; + + // rapprochement artificiel si texture de type decoration + int decoration = (texture->decoration ? DECORATION_OFFSET : 0); + + // acces a la vram + char* vram = get_vram_address(); + unsigned char mask_vram, mask_w; + int offset_vram; + int address; + + int u0, u1, u2; + int z_num, z_div; + int w, h; + + // pre-calcul largeur en octet des tableaux + int nbw_tex = ((texture->pixel_width - 1) >> 3) + 1; + char loop_w_tex = texture->pixel_width-1; + char loop_h_tex = texture->pixel_height-1; + + // parcours en ligne + for(int x=min_x; x<=max_x; x++) + { + u0 = u0_start; u1 = u1_start; u2 = u2_start; + z_num = z_num_start; + z_div = z_div_start; + offset_vram = x >> 3; + mask_vram = 128 >> (x & 7); + // parcours en colonne + for(int y=min_y; y<=max_y; y++) + { + // si le pixel (x;y) est dans le triangle + if ((u0 | u1 | u2) > 0) + { + // addresse du z-buffer + address = x + y * z_buffer_width + z_buffer_offset; + // si le pixel (x;y) est plus proche qu'avant + if (z_num <= z_buffer[address] + decoration) + { + // calcul des coordonnees pour la texture + w = ((u0 * w0 + u1 * w1 + u2 * w2) / z_div) & loop_w_tex; + h = ((u0 * h0 + u1 * h1 + u2 * h2) / z_div) & loop_h_tex; + // calcul du masque pour l'octet + mask_w = 128 >> (w & 7); + if (texture->mask == NULL) + { + // enregistre la profondeur du pixel dans le z buffer + z_buffer[address] = z_num; + if ((texture->sprite[(w >> 3) + (h * nbw_tex)] & mask_w)) + { + // afficher pixel noir + vram[(y << 4) + offset_vram] |= mask_vram; + }else{ + // afficher pixel blanc + vram[(y << 4) + offset_vram] &= ~mask_vram; + } + // curseur + pixel_on_cursor(x, y); + } else { + int alpha = (w >> 3) + (h * nbw_tex); + if ((texture->mask[alpha] & mask_w)) + { + // enregistre la profondeur du pixel dans le z buffer + z_buffer[address] = z_num; + if ((texture->sprite[alpha] & mask_w)) + { + // afficher pixel noir + vram[(y << 4) + offset_vram] |= mask_vram; + }else{ + // afficher pixel blanc + vram[(y << 4) + offset_vram] &= ~mask_vram; + } + // curseur + pixel_on_cursor(x, y); + } + } + + } + } + u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y; + z_num += z_num_step_y; + z_div += z_div_step_y; + } + u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x; + z_num_start += z_num_step_x; + z_div_start += z_div_step_x; + } +} + + + + +void Windmill::render_triangle_black(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC) +{ + // calcul du rectangle circonscrit au triangle + int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x))); + int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x))); + int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y))); + int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y))); + + // calcul de l'aire du triangle + int area = edge(vertexA, vertexB, vertexC); + // termine si la taille du triangle est trop petite + if (area <= MIN_AREA_CLIP) return; + + // calcul des produits vectoriels + int u0_start = edge_start(vertexB, vertexC, min_x, min_y); + int u0_step_x = edge_step_x(vertexB, vertexC); + int u0_step_y = edge_step_y(vertexB, vertexC); + int u1_start = edge_start(vertexC, vertexA, min_x, min_y); + int u1_step_x = edge_step_x(vertexC, vertexA); + int u1_step_y = edge_step_y(vertexC, vertexA); + int u2_start = edge_start(vertexA, vertexB, min_x, min_y); + int u2_step_x = edge_step_x(vertexA, vertexB); + int u2_step_y = edge_step_y(vertexA, vertexB); + + int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area; + int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area; + int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area; + + // acces a la vram + char* vram = get_vram_address(); + unsigned char mask_vram; + int offset_vram; + int address; + + int u0, u1, u2; + int z_num; + + // parcours en ligne + for(int x=min_x; x<=max_x; x++) + { + u0 = u0_start; u1 = u1_start; u2 = u2_start; + z_num = z_num_start; + offset_vram = x >> 3; + mask_vram = 128 >> (x & 7); + // parcours en colonne + for(int y=min_y; y<=max_y; y++) + { + // si le pixel (x;y) est dans le triangle + if ((u0 | u1 | u2) > 0) + { + // addresse du z-buffer + address = x + y * z_buffer_width + z_buffer_offset; + // si le pixel (x;y) est plus proche qu'avant + if (z_num <= z_buffer[address]) + { + // enregistre la profondeur du pixel dans le z buffer + z_buffer[address] = z_num; + // afficher pixel noir + vram[(y << 4) + offset_vram] |= mask_vram; + // curseur + pixel_on_cursor(x, y); + } + } + u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y; + z_num += z_num_step_y; + } + u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x; + z_num_start += z_num_step_x; + } +} + +/* +void Windmill::render_triangle_black(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC) +{ + // calcul du rectangle circonscrit au triangle + int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x))); + int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x))); + int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y))); + int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y))); + + // calcul de l'aire du triangle + int area = edge(vertexA, vertexB, vertexC); + // termine si la taille du triangle est trop petite + if (area <= MIN_AREA_CLIP) return; + + // calcul des produits vectoriels + int u0_start = edge_start(vertexB, vertexC, min_x, min_y); + int u0_step_x = edge_step_x(vertexB, vertexC); + int u0_step_y = edge_step_y(vertexB, vertexC); + int u1_start = edge_start(vertexC, vertexA, min_x, min_y); + int u1_step_x = edge_step_x(vertexC, vertexA); + int u1_step_y = edge_step_y(vertexC, vertexA); + int u2_start = edge_start(vertexA, vertexB, min_x, min_y); + int u2_step_x = edge_step_x(vertexA, vertexB); + int u2_step_y = edge_step_y(vertexA, vertexB); + + int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area; + int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area; + int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area; + + // acces a la vram +// char* vram = get_vram_address(); + unsigned char mask_vram; + int offset_vram; + int address; + + int u0, u1, u2; + int z_num; + + // parcours en ligne + for(int x=min_x; x<=max_x; x++) + { + u0 = u0_start; u1 = u1_start; u2 = u2_start; + z_num = z_num_start; + offset_vram = x >> 3; + mask_vram = 128 >> (x & 7); + // parcours en colonne + for(int y=min_y; y<=max_y; y++) + { + // si le pixel (x;y) est dans le triangle + if ((u0 | u1 | u2) > 0) + { + // addresse du z-buffer + address = x + y * z_buffer_width + z_buffer_offset; + // si le pixel (x;y) est plus proche qu'avant + if (z_num <= z_buffer[address]) + { + // enregistre la profondeur du pixel dans le z buffer + z_buffer[address] = z_num; + // afficher pixel noir +// vram[(y << 4) + offset_vram] |= mask_vram; + // curseur + pixel_on_cursor(x, y); + } + } + u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y; + z_num += z_num_step_y; + } + u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x; + z_num_start += z_num_step_x; + } +} +*/ + +void Windmill::render_triangle_white(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC) +{ + // calcul du rectangle circonscrit au triangle + int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x))); + int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x))); + int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y))); + int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y))); + + // calcul de l'aire du triangle + int area = edge(vertexA, vertexB, vertexC); + // termine si la taille du triangle est trop petite + if (area <= MIN_AREA_CLIP) return; + + // calcul des produits vectoriels + int u0_start = edge_start(vertexB, vertexC, min_x, min_y); + int u0_step_x = edge_step_x(vertexB, vertexC); + int u0_step_y = edge_step_y(vertexB, vertexC); + int u1_start = edge_start(vertexC, vertexA, min_x, min_y); + int u1_step_x = edge_step_x(vertexC, vertexA); + int u1_step_y = edge_step_y(vertexC, vertexA); + int u2_start = edge_start(vertexA, vertexB, min_x, min_y); + int u2_step_x = edge_step_x(vertexA, vertexB); + int u2_step_y = edge_step_y(vertexA, vertexB); + + int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area; + int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area; + int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area; + + // acces a la vram + char* vram = get_vram_address(); + unsigned char mask_vram; + int offset_vram; + int address; + + int u0, u1, u2; + int z_num; + + // parcours en ligne + for(int x=min_x; x<=max_x; x++) + { + u0 = u0_start; u1 = u1_start; u2 = u2_start; + z_num = z_num_start; + offset_vram = x >> 3; + mask_vram = 128 >> (x & 7); + // parcours en colonne + for(int y=min_y; y<=max_y; y++) + { + // si le pixel (x;y) est dans le triangle + if ((u0 | u1 | u2) > 0) + { + // addresse du z-buffer + address = x + y * z_buffer_width + z_buffer_offset; + // si le pixel (x;y) est plus proche qu'avant + if (z_num <= z_buffer[address]) + { + // enregistre la profondeur du pixel dans le z buffer + z_buffer[address] = z_num; + // afficher pixel blanc + vram[(y << 4) + offset_vram] &= ~mask_vram; + // curseur + pixel_on_cursor(x, y); + } + } + u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y; + z_num += z_num_step_y; + } + u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x; + z_num_start += z_num_step_x; + } +} + + +void Windmill::render_triangle_transparent(Vertex* vertexA, Vertex* vertexB, Vertex* vertexC, const Texture* texture) +{ + // calcul du rectangle circonscrit au triangle + int min_x = max(viewport.x1, min(vertexA->x, min(vertexB->x, vertexC->x))); + int max_x = min(viewport.x2-1, max(vertexA->x, max(vertexB->x, vertexC->x))); + int min_y = max(viewport.y1, min(vertexA->y, min(vertexB->y, vertexC->y))); + int max_y = min(viewport.y2-1, max(vertexA->y, max(vertexB->y, vertexC->y))); + + // calcul de l'aire du triangle + int area = edge(vertexA, vertexB, vertexC); + // termine si la taille du triangle est trop petite + if (area <= MIN_AREA_CLIP) return; + + // pre-calcul des coordonnees de la texture + int w0 = vertexA->w * vertexA->z; int h0 = vertexA->h * vertexA->z; + int w1 = vertexB->w * vertexB->z; int h1 = vertexB->h * vertexB->z; + int w2 = vertexC->w * vertexC->z; int h2 = vertexC->h * vertexC->z; + + // calcul des produits vectoriels + int u0_start = edge_start(vertexB, vertexC, min_x, min_y); + int u0_step_x = edge_step_x(vertexB, vertexC); + int u0_step_y = edge_step_y(vertexB, vertexC); + int u1_start = edge_start(vertexC, vertexA, min_x, min_y); + int u1_step_x = edge_step_x(vertexC, vertexA); + int u1_step_y = edge_step_y(vertexC, vertexA); + int u2_start = edge_start(vertexA, vertexB, min_x, min_y); + int u2_step_x = edge_step_x(vertexA, vertexB); + int u2_step_y = edge_step_y(vertexA, vertexB); + + int z_num_start = (u0_start * vertexA->z_normalized + u1_start * vertexB->z_normalized + u2_start * vertexC->z_normalized) / area; + int z_num_step_x = (u0_step_x * vertexA->z_normalized + u1_step_x * vertexB->z_normalized + u2_step_x * vertexC->z_normalized) / area; + int z_num_step_y = (u0_step_y * vertexA->z_normalized + u1_step_y * vertexB->z_normalized + u2_step_y * vertexC->z_normalized) / area; + + int z_div_start = u0_start * vertexA->z + u1_start * vertexB->z + u2_start * vertexC->z; + int z_div_step_x = u0_step_x * vertexA->z + u1_step_x * vertexB->z + u2_step_x * vertexC->z; + int z_div_step_y = u0_step_y * vertexA->z + u1_step_y * vertexB->z + u2_step_y * vertexC->z; + + // acces a la vram + char* vram = get_vram_address(); + + // pre-calcul largeur en octet des tableaux + int nbw_tex = ((texture->pixel_width - 1) >> 3) + 1; + char loop_w_tex = texture->pixel_width-1; + char loop_h_tex = texture->pixel_height-1; + + // parcours en ligne + for(int x=min_x; x<=max_x; x++) + { + int u0 = u0_start; int u1 = u1_start; int u2 = u2_start; + int z_num = z_num_start; + int z_div = z_div_start; + int offset_vram = x >> 3; + char mask_vram = 128 >> (x & 7); + // parcours en colonne + for(int y=min_y; y<=max_y; y++) + { + // si le pixel (x;y) est dans le triangle + if ((u0 | u1 | u2) > 0) + { + // addresse du z-buffer + int address = x + y * z_buffer_width + z_buffer_offset; + // si le pixel (x;y) est plus proche qu'avant + if (z_num <= z_buffer[address]) + { + // calcul des coordonnees pour la texture + unsigned int w = ((u0 * w0 + u1 * w1 + u2 * w2) / z_div) & loop_w_tex; + unsigned int h = ((u0 * h0 + u1 * h1 + u2 * h2) / z_div) & loop_h_tex; + // calcul du masque pour l'octet + unsigned char mask_w = 128 >> (w & 7); + if ((texture->sprite[(w >> 3) + (h * nbw_tex)] & mask_w)) + { + // afficher pixel noir + vram[(y << 4) + offset_vram] |= mask_vram; + // enregistre la profondeur du pixel dans le z buffer + z_buffer[address] = z_num; + } + } + } + u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y; + z_num += z_num_step_y; + z_div += z_div_step_y; + } + u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x; + z_num_start += z_num_step_x; + z_div_start += z_div_step_x; + } +} + + + + +/* +//----------------------------------------------------------------------------- +// load_map +// Ritter's bounding sphere +//----------------------------------------------------------------------------- +void Windmill::load_map(Map* _map) +{ + if (map != _map) + { + map = _map; + delete[] sphere; + sphere = new Bounding_Sphere [map->list_object_length]; + for (int i = 0; ilist_object_length; i++) + { + Object* current_object = map->object[i]; + + int nb_point; + for (int j = 0; jmodele_size; j++) + { + nb_point += current_object->modele[j].type; + } + + Point* point = get_point(current_object, 0); + int min_x = point->x; + int min_y = point->y; + int min_z = point->z; + int max_x = min_x; + int max_y = min_y; + int max_z = min_z; + + for (int j = 0; jx < min_x) + min_x = point->x; + if(point->y < min_y) + min_y = point->y; + if(point->z < min_z) + min_z = point->z; + + if(point->x > max_x) + max_x = point->x; + if(point->y > max_y) + max_y = point->y; + if(point->z > max_z) + max_z = point->z; + } + int xdiff = max_x - min_x; + int ydiff = max_y - min_y; + int zdiff = max_z - min_y; + + int diameter = max(xdiff, max(ydiff, zdiff)); //take max as diameter + glm::vec3 centre = (vmax+vmin)*(0.5f); + float radius = diameter/2; + float sq_radius = radius*radius; + + for(int i=0; i sq_radius) + { + float distance = sqrt(sq_distance); + + float difference = distance - radius; + + float new_diameter = 2 * radius + difference; + sq_radius = radius * radius; + + difference /= 2; + + centre += difference * direction; + } + } + + + + } + } +}*/ + + + + + +//---------------------------------------------------------------------------------------------------- +// MANIPULATION +//---------------------------------------------------------------------------------------------------- +Point Windmill::get_point(const Modele* poly, int i) +{ + Point point; + if (i == 0) + { + point.x = poly->x0; point.y = poly->y0; point.z = poly->z0; + } + if (i == 1) + { + point.x = poly->x1; point.y = poly->y1; point.z = poly->z1; + } + if (i == 2) + { + point.x = poly->x2; point.y = poly->y2; point.z = poly->z2; + } + if (i == 3) + { + if (poly->option == PARA) + { + point.x = poly->x2 + poly->x1 - poly->x0; + point.y = poly->y2 + poly->y1 - poly->y0; + point.z = poly->z2 + poly->z1 - poly->z0; + } else if (poly->option == TRAP) + { + point.x = poly->x2 - poly->x1 + poly->x0; + point.y = poly->y2 - poly->y1 + poly->y0; + point.z = poly->z2 - poly->z1 + poly->z0; + } + } + return point; +} + + +Point Windmill::get_center_poly(const Modele* poly) +{ + Point point; + point.x = 0; point.y = 0; point.z = 0; + + for (int i = 0; i < poly->type; i++) + { + point.x += get_point(poly, i).x; + point.y += get_point(poly, i).y; + point.z += get_point(poly, i).z; + } + + point.x /= poly->type; + point.y /= poly->type; + point.z /= poly->type; + + return point; +} + + +void Windmill::compute_object_angle(Object* object, int* cosinus, int* sinus) +{ + if (object->axe == Z_BILLBOARD) + { + float angle_look_at_camera = atan2f(camera.y - object->y, camera.x - object->x); + float angle_rad = angle_look_at_camera + 3.1415 * object->angle / 180.0; + *cosinus = 1024 * cosf(angle_rad); + *sinus = 1024 * sinf(angle_rad); + } + if (object->axe == X or object->axe == Y or object->axe == Z) + { + float angle_rad = 3.1415 * object->angle / 180.0; + *cosinus = 1024 * cosf(angle_rad); + *sinus = 1024 * sinf(angle_rad); + } +} + + +void Windmill::extract_vertex_from_poly(const Modele* poly, Vertex* vertex, int* vertex_length, int* width, int* height) +{ + int x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3; + + if (poly->type == TRIANGLE) + { + *vertex_length = 3; + x0 = poly->x0; y0 = poly->y0; z0 = poly->z0; + x1 = poly->x1; y1 = poly->y1; z1 = poly->z1; + x2 = poly->x2; y2 = poly->y2; z2 = poly->z2; + vertex[0].set_xyz(x0, y0, z0); + vertex[1].set_xyz(x1, y1, z1); + vertex[2].set_xyz(x2, y2, z2); + *width = distance(x0-x1, y0-y1, z0-z1); + *height = distance(x0-x2, y0-y2, z0-z2); + } + if (poly->type == RECTANGLE) + { + *vertex_length = 4; + x0 = poly->x0; y0 = poly->y0; z0 = poly->z0; + x1 = poly->x1; y1 = poly->y1; z1 = poly->z1; + x3 = poly->x2; y3 = poly->y2; z3 = poly->z2; + if (poly->option == PARA) + { + x2 = x3 + x1 - x0; y2 = y3 + y1 - y0; z2 = z3 + z1 - z0; + } else if (poly->option == TRAP) + { + //x2 = x3 - x1 + x0; y2 = y3 - y1 + y0; z2 = z3 - z1 + z0; + } + vertex[0].set_xyz(x0, y0, z0); + vertex[1].set_xyz(x1, y1, z1); + vertex[2].set_xyz(x2, y2, z2); + vertex[3].set_xyz(x3, y3, z3); + *width = distance(x0-x1, y0-y1, z0-z1); + *height = distance(x0-x3, y0-y3, z0-z3); + } +} + + +void Windmill::texture_coordinates(const Modele* poly, Vertex* vertex, const Texture* texture, int visible, int width, int height) +{ + int w = (texture->real_width > 0) ? width * texture->pixel_width / texture->real_width : texture->pixel_width; + int h = (texture->real_height > 0) ? height * texture->pixel_height / texture->real_height : texture->pixel_height; + + if (poly->type == TRIANGLE) + { + int offset = w * texture->offset; + if (visible == FRONT or texture->mirror == true) + { + vertex[0].set_wh(0, texture->pixel_height); + vertex[1].set_wh(w, texture->pixel_height); + vertex[2].set_wh(offset, texture->pixel_height-h); + // vertex[0].set_wh(0, h); + // vertex[1].set_wh(w, h); + // vertex[2].set_wh(offset, 0); + } else { + vertex[0].set_wh(w, h); + vertex[1].set_wh(0, h); + vertex[2].set_wh(w-offset, 0); + } + } + else if (poly->type == RECTANGLE) + { + if (visible == FRONT or texture->mirror == true) + { + vertex[0].set_wh(0, texture->pixel_height); + vertex[1].set_wh(w, texture->pixel_height); + vertex[2].set_wh(w, texture->pixel_height-h); + vertex[3].set_wh(0, texture->pixel_height-h); + + // vertex[0].set_wh(0, h); + // vertex[1].set_wh(w, h); + // vertex[2].set_wh(w, 0); + // vertex[3].set_wh(0, 0); + } else { + vertex[0].set_wh(w, h); + vertex[1].set_wh(0, h); + vertex[2].set_wh(0, 0); + vertex[3].set_wh(w, 0); + } + } +} + + +void Windmill::swap_vertex(Vertex* vertexA, Vertex* vertexB) +{ + Vertex vertex_temp; + memcpy(&vertex_temp, vertexA, sizeof(Vertex)); + memcpy(vertexA, vertexB, sizeof(Vertex)); + memcpy(vertexB, &vertex_temp, sizeof(Vertex)); +} + + +void Windmill::copy_vertex(Vertex* vertex_source, Vertex* vertex_dest) +{ + memcpy(vertex_dest, vertex_source, sizeof(Vertex)); +} + + + +//---------------------------------------------------------------------------------------------------- +// SPHERE +//---------------------------------------------------------------------------------------------------- +Sphere Windmill::transform_sphere_to_world(Sphere* sphere_input, Object* object, int cosinus, int sinus) +{ + Vertex vertex; + vertex.set_xyz(sphere_input->x, sphere_input->y, sphere_input->z); + transform_model_to_world(&vertex, 1, object, cosinus, sinus); + transform_world_to_camera(&vertex, 1); + Sphere sphere_output; + sphere_output.x = vertex.x >> 7; + sphere_output.y = vertex.y >> 7; + sphere_output.z = vertex.z >> 7; + sphere_output.radius = sphere_input->radius; + + return sphere_output; +} + +/* +bool Windmill::sphere_in_cone(Sphere* sphere) +{ + //return true; + int cone_offset = sphere->radius * camera.sin_fov; + + int nx = camera.nx; + int ny = camera.ny; + int nz = camera.nz; + + Point cone; + cone.x = int(camera.x) - ((nx * cone_offset) >> 14); + cone.y = int(camera.y) - ((ny * cone_offset) >> 14); + cone.z = int(camera.z) - ((nz * cone_offset) >> 14); + + int sx = sphere->x - cone.x; + int sy = sphere->y - cone.y; + int sz = sphere->z - cone.z; + int ss = sx*sx + sy*sy + sz*sz; + + // si sommet du cone dans la sphere + if (ss <= sphere->radius * sphere->radius) + { + return true; + } + + // si sphere dans le cone + int ns = ((nx * sx) >> 7) + ((ny * sy) >> 7) + ((nz * sz) >> 7); + + if (ns > 0 and ns*ns > camera.cos_fov_square * ss) + { + return true; + } + return false; +}*/ + +bool Windmill::sphere_in_cone(Sphere* sphere) +{ + //return true; + sphere->z += sphere->radius; + if (sphere->z > 0) + { + int sphere_z = int(sphere->z * camera.scale_coef) >> 6; + int xr = 0; + if (sphere->x > 0) xr = sphere->x - sphere->radius; + if (sphere->x < 0) xr = - sphere->x - sphere->radius; + + if (xr <= sphere_z) return true; + } + return false; +} + + + +//---------------------------------------------------------------------------------------------------- +// DIVERS +//---------------------------------------------------------------------------------------------------- +void Windmill::copy_camera() +{ + memcpy(&camera, camera2, sizeof(Camera)); +} + + +void Windmill::sort_object() +{ + //qsort(object, list_object_length, sizeof(Object*), compare_object); +} + + +int compare_object(void const *a, void const *b) +{ + Object* object_a = *(Object **) a; + Object* object_b = *(Object **) b; + return (object_a->distance_to_camera - object_b->distance_to_camera); +} + + +void Windmill::clear_z_buffer() +{ + memset(z_buffer, MAX_DEPTH_Z_BUFFER, z_buffer_size * sizeof(short)); +} + + +int Windmill::edge(Vertex* a, Vertex* b, Vertex* c) +{ + return (c->x - a->x) * (b->y - a->y) - (c->y - a->y) * (b->x - a->x); +} + + +int Windmill::edge_start(Vertex* a, Vertex* b, int px, int py) +{ + return (b->y - a->y) * (px - a->x) - (b->x - a->x) * (py - a->y); +} + + +int Windmill::edge_step_x(Vertex* a, Vertex* b) +{ + return b->y - a->y; +} + + +int Windmill::edge_step_y(Vertex* a, Vertex* b) +{ + return a->x - b->x; +} + + + +//---------------------------------------------------------------------------------------------------- +// UTILITAIRE +//---------------------------------------------------------------------------------------------------- +void Windmill::pixel_on_cursor(int x, int y) +{ + if (x == cursor_x and y == cursor_y) + { + temp_object_cursor = object[i]; + temp_poly_cursor = j; + } +} + + +void Windmill::show_coordinates() +{ + // coordonnees + float tab_coordinates[5] = {camera.x, camera.y, camera.z, to_deg(camera.yaw), to_deg(camera.pitch)}; + for (int i = 0; i < 5; i++) + { + /* + char str[20]; + sprintf(str, "%f", tab_coordinates[i]); + int j; + for(j= 0; j < 16; j++) + { + if (str[j] == '.') + { + str[j+2] = '\0'; + break; + } + } + PrintMini(127-4*(j+2), 1+6*i, (unsigned char*)str, MINI_OVER);*/ + dprint(0, 1+6*i, C_BLACK, "%f", tab_coordinates[i]); // need Gint + } +} + + +void Windmill::show_repere() +{/* + // repere + int repere_x = 112; + int repere_y = 55; + int repere_size = 12; + + float camera_yaw_rad = -camera.yaw;//- 3.1415 * camera.yaw / 180.0; + float camera_pitch_rad = camera.pitch;//3.1415 * camera.pitch / 180.0; + float cos_yaw = cosf(camera_yaw_rad); + float sin_yaw = sinf(camera_yaw_rad); + float cos_pitch = cosf(camera_pitch_rad); + float sin_pitch = sinf(camera_pitch_rad); + float aa4 = sin_yaw; + float aa5 = cos_yaw; + float aa6 = 0; + float aa7 = -sin_pitch * cos_yaw; + float aa8 = sin_pitch * sin_yaw; + float aa9 = cos_pitch; + // repere + Vertex v[3]; + //const unsigned char* cx = "x"; + //const unsigned char* cy = "y"; + //const unsigned char* cz = "z"; + const char* letter[] = {"x", "y", "z"}; + v[0].set_xyz(repere_size, 0 , 0 ); + v[1].set_xyz(0 , repere_size, 0 ); + v[2].set_xyz(0 , 0 , repere_size); + for (int i = 0; i < 3; i++) + { + float y = (aa4 * v[i].x + aa5 * v[i].y + aa6 * v[i].z); + float z = (aa7 * v[i].x + aa8 * v[i].y + aa9 * v[i].z); + v[i].x = -y; + v[i].y = -z; + //ML_line(repere_x, repere_y, v[i].x + repere_x, v[i].y + repere_y, ML_BLACK); + //PrintMini(v[i].x + repere_x, v[i].y + repere_y-2, letter[i], MINI_OVER); + } + */ +} + + +/*void Windmill::show_fps() +{ + char str[20]; + sprintf(str, "%i", time_get_fps()); + PrintMini(1, 58, (unsigned char*)str, MINI_OVER); +}*/ + + + + +//---------------------------------------------------------------------------------------------------- +// DESTRUCTEUR +//---------------------------------------------------------------------------------------------------- +Windmill::~Windmill() +{ + free(z_buffer); + free(object); + //delete[] object; +} + + + + + +float distance(float dx, float dy, float dz) +{ + return sqrtf(dx*dx + dy*dy + dz*dz); +} + +Vertex::Vertex(){} + +void Vertex::set_xyz(int _x, int _y, int _z) +{ + x = _x; + y = _y; + z = _z; +} + +void Vertex::set_wh(float _w, float _h) +{ + w = _w; + h = _h; +} + +float Vertex::length(int x, int y, int z) +{ + return sqrtf(x*x + y*y + z*z); +} diff --git a/src/windmill.hpp b/src/windmill.hpp new file mode 100644 index 0000000..56fc9b3 --- /dev/null +++ b/src/windmill.hpp @@ -0,0 +1,257 @@ +#ifndef DEF_WINDMILL +#define DEF_WINDMILL + + +extern "C" +{ + #define __BSD_VISIBLE 1 + #include + #include // pour affichage des coordonnées + #include + #include + #include +} +#include "camera.hpp" + +#define get_vram_address() ((char *)gint_vram) + +// parametrage de Windmill +#define MIN_AREA_CLIP 5 +#define DECORATION_OFFSET 50 +#define MAX_DEPTH_Z_BUFFER 0xffff + +enum {N, X, Y, Z, Z_BILLBOARD}; +#define FRONT 1 +#define BACK -1 +#define RIEN 0 +#define TRIANGLE 3 +#define RECTANGLE 4 +#define PARA 0 +#define TRAP 1 + +#define INTERIEUR true +#define EXTERIEUR false + +// pour la collision +#define INSIDE -1 +#define ALL 127 +#define NONE 0 +//#define OUT 1 +//#define IN 0 + + + +// definition des structures +struct Point +{ + int x, y, z; +}; + +class Vecteur +{ +public: + float x1, y1, x2, y2; +}; + +struct Sphere +{ + int x, y, z; + int radius; +}; + +class Vertex +{ +public: + int x, y, z; + float w, h; + unsigned short z_normalized; + + Vertex(); + void set_xyz(int _x, int _y, int _z); + void set_wh(float _w, float _h); + float length(int x, int y, int z); +}; + + +struct Texture +{ + const unsigned char* sprite; + const unsigned char* mask; + const char pixel_width; + const char pixel_height; + const char real_width; + const char real_height; + const float offset; + const bool transparent; + const bool decoration; + const bool mirror; +}; + + +struct Modele +{ + const int type; + const Texture* texture_front; + const Texture* texture_back; + const short x0, y0, z0; + const short x1, y1, z1; + const short x2, y2, z2; + const char option; +}; + + +struct Object +{ + short x, y, z; + float angle; + char axe; + const Modele* modele; + const int modele_size; + // ajouter ici + const char collision; + //const char for_collision; + //const char type_collision; + bool hidden; + Sphere sphere; + int distance_to_camera; + bool on_screen; +}; + + +struct Map +{ + Object** object; + int list_object_length; + bool horizon; + bool ground; + // ajouter ici +}; + +struct Viewport +{ + int x1, y1, x2, y2; +}; + + +float distance(float dx, float dy, float dz); +int compare_object(void const *a, void const *b); + + +class Windmill +{ +public: + // initialisation et parametrage + Windmill(); + void set_camera(Camera* _camera); + void set_viewport(int viewport_x1, int viewport_y1, int viewport_x2, int viewport_y2); + void load_map(Map* _map); + + // dessin + void draw(); + void draw_horizon(); + void draw_ground(); + void draw_objects(); + void draw_post_treatment(); + void draw_body(); + + // transformation 3D des vertex + void transform_model_to_world(Vertex vertex[], int vertex_length, Object* object, int cosinus, int sinus); + void transform_world_to_camera(Vertex vertex[], int vertex_length); + void transform_camera_to_screen(Vertex vertex[], int vertex_length); + void transform_camera_to_screen2(Vertex vertex[], int vertex_length); + + // text visiblilite + bool fast_check(Vertex vertex_list[], int vertex_list_length); + bool inside_viewport(int x, int y); + int visible_face(Vertex* a, Vertex* b, Vertex* c); + + void clip_depth(Vertex vertex_list_input[], int* vertex_list_input_length); + void clip_depth_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set); + bool clip_depth_inside_edge(Vertex* vertex); + + void clip_viewport(Vertex vertex_list_input[], int* vertex_list_input_length); + void clip_viewport_edge(Vertex* vertex_in, Vertex* vertex_out, Vertex* vertex_set, int edge); + bool clip_viewport_inside_edge(Vertex* vertex, int edge); + + // dessin des triangles + void render_triangle(Vertex* vertex1, Vertex* vertex2, Vertex* vertex3, const Texture *texture); + void render_triangle_texture(Vertex* vertex1, Vertex* vertex2, Vertex* vertex3, const Texture* texture); + void render_triangle_black(Vertex* vertex0, Vertex* vertex1, Vertex* vertex2); + void render_triangle_white(Vertex* vertex0, Vertex* vertex1, Vertex* vertex2); + void render_triangle_transparent(Vertex* vertex1, Vertex* vertex2, Vertex* vertex3, const Texture* texture); + + // manipulation + Point get_point(const Modele* poly, int i); + Point get_center_poly(const Modele* poly); + void compute_object_angle(Object* object, int* cosinus, int* sinus); + void extract_vertex_from_poly(const Modele* poly, Vertex* vertex, int* vertex_length, int* width, int* height); + void texture_coordinates(const Modele* poly, Vertex* vertex, const Texture* texture, int visible, int width, int height); + void swap_vertex(Vertex* vertexA, Vertex* vertexB); + void copy_vertex(Vertex* vertex_source, Vertex* vertex_dest); + + // sphere + Sphere transform_sphere_to_world(Sphere* sphere, Object* object, int cosinus, int sinus); + bool sphere_in_cone(Sphere* sphere); + + // divers + void copy_camera(); + void sort_object(); + void clear_z_buffer(); + int edge(Vertex* a, Vertex* b, Vertex* c); + int edge_start(Vertex* a, Vertex* b, int px, int py); + int edge_step_x(Vertex* a, Vertex* b); + int edge_step_y(Vertex* a, Vertex* b); + + // utilitaires + void pixel_on_cursor(int x, int y); + void show_coordinates(); + void show_repere(); + //void show_fps(); + + // destructeurr + ~Windmill(); + +private: + // camera + Camera* camera2; // camera a suivre + Camera camera; // camera_temporaire + + // carte + Map* map; + + // liste objets triee + Object** object; + int list_object_length; + + // z_buffer + int shift_x, shift_y; + unsigned short* z_buffer; + int z_buffer_size; + int z_buffer_offset; + int z_buffer_width; + + // en cours + int i; + int j; + + // variables temporaire pour eviter de lire la valeur en cours de calcul + int temp_nb_object_on_screen; + Object* temp_object_cursor; + int temp_poly_cursor; + +public: + // fenetre de visualisation + Viewport viewport; + + // utilitaires + bool loading; + int nb_object_on_screen; + Object* object_cursor; + int poly_cursor; + int cursor_x; + int cursor_y; +}; + + + +#endif