initial-with-some-changes

This commit is contained in:
Lephenixnoir 2021-06-18 11:48:50 +02:00
commit 7d08a2ffef
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
54 changed files with 5443 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Build files
/build-fx
/build-cg
/*.g1a
/*.g3a
# Python bytecode
__pycache__/
# Common IDE files
*.sublime-project
*.sublime-workspace
.vscode

86
CMakeLists - Kikoudx.txt Normal file
View File

@ -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()

61
CMakeLists.txt Normal file
View File

@ -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()

45
LEPHE.md Normal file
View File

@ -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<lettre>,<options>` 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 `<gint/defs/attributes.h>`) 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 `<gint/display.h>`. 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.

BIN
assets-cg/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,3 @@
example.png:
type: bopti-image
name: img_example

BIN
assets-cg/icon-sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
assets-cg/icon-uns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets-fx/.DS_Store vendored Normal file

Binary file not shown.

BIN
assets-fx/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,7 @@
example.png:
type: bopti-image
name: img_example
img/windmill.png:
type: bopti-image
name: img_windmill

BIN
assets-fx/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
assets-fx/img/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
assets-fx/img/brique.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

BIN
assets-fx/img/forgeron.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

View File

@ -0,0 +1,3 @@
windmill.png:
type: bopti-image
name: img_windmill

BIN
assets-fx/img/haie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

BIN
assets-fx/img/herbe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

BIN
assets-fx/img/horloge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

BIN
assets-fx/img/paille.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

BIN
assets-fx/img/panneau.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

BIN
assets-fx/img/table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

BIN
assets-fx/img/windmill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

BIN
assets-fx/img/windmill2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

87
src/Scene_Title.cpp Normal file
View File

@ -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
}

122
src/Scene_Title.hpp Normal file
View File

@ -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

196
src/camera.cpp Normal file
View File

@ -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;
}
*/

123
src/camera.hpp Normal file
View File

@ -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 <openlibm.h>
#include <gint/defs/util.h>
}
//#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

33
src/game.cpp Normal file
View File

@ -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);
}

93
src/game.hpp Normal file
View File

@ -0,0 +1,93 @@
#ifndef DEF_GAME
#define DEF_GAME
extern "C"
{
#define __BSD_VISIBLE 1
#include <openlibm.h>
//#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

39
src/main.cpp Normal file
View File

@ -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;
}

9
src/main.hpp Normal file
View File

@ -0,0 +1,9 @@
extern "C"
{
#include <gint/display.h>
#include <gint/keyboard.h>
}
#include "game.hpp"
#include "windmill.hpp"
#include "scene_map.hpp"

1427
src/map.cpp Normal file

File diff suppressed because it is too large Load Diff

49
src/player.cpp Normal file
View File

@ -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;
}

52
src/player.hpp Normal file
View File

@ -0,0 +1,52 @@
#ifndef DEF_PLAYER
#define DEF_PLAYER
extern "C"
{
#define __BSD_VISIBLE 1
#include <openlibm.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;
};
#endif

849
src/scene_map.cpp Normal file
View File

@ -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; i<game.map->list_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; j<nb_poly; j++)
{
const Modele* current_modele = &current_object->modele[j];
for (int k=0; k<current_modele->type; 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; i<game.map->list_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; i<game.map->list_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; i<game.map->list_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
}

101
src/scene_map.hpp Normal file
View File

@ -0,0 +1,101 @@
#ifndef DEF_SCENE_MAP
#define DEF_SCENE_MAP
extern "C"
{
#include <gint/defs/util.h>
#include <gint/keyboard.h>
}
#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

1788
src/windmill.cpp Normal file

File diff suppressed because it is too large Load Diff

257
src/windmill.hpp Normal file
View File

@ -0,0 +1,257 @@
#ifndef DEF_WINDMILL
#define DEF_WINDMILL
extern "C"
{
#define __BSD_VISIBLE 1
#include <openlibm.h>
#include <gint/display.h> // pour affichage des coordonnées
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/defs/util.h>
}
#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