2021-07-29 18:33:22 +02:00
|
|
|
#include <gint/display.h>
|
|
|
|
#include <gint/keyboard.h>
|
|
|
|
#include "engine.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "map.h"
|
|
|
|
#include "player.h"
|
2021-07-31 18:44:06 +02:00
|
|
|
#include "animation.h"
|
2021-08-04 20:12:53 +02:00
|
|
|
#include "define.h"
|
2021-08-07 01:49:03 +02:00
|
|
|
#include "character.h"
|
2021-08-19 02:29:51 +02:00
|
|
|
#include "camera.h"
|
2021-07-29 18:33:22 +02:00
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*draw the current state of the game*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_draw(struct Game const *game) {
|
2021-08-05 03:12:40 +02:00
|
|
|
dclear(game->background);
|
2021-08-19 02:29:51 +02:00
|
|
|
//engine_draw_map_around_player(game);
|
|
|
|
engine_draw_map(game);
|
2021-08-04 20:12:53 +02:00
|
|
|
engine_draw_player(game->player);
|
|
|
|
}
|
2021-07-30 02:01:05 +02:00
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*draw the map around the player*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_draw_map_around_player(struct Game const *game) {
|
2021-08-04 20:12:53 +02:00
|
|
|
const int level_width = game->map->w;
|
|
|
|
const int taillemap = game->map->w * game->map->h;
|
|
|
|
const int posx = game->player->show_x;
|
|
|
|
const int posy = game->player->show_y;
|
|
|
|
|
|
|
|
const int coo_player_map = game->player->x + game->player->y*level_width; //the index of the player on the map
|
|
|
|
int beginmap = coo_player_map - PLAYER_VIEW_X - level_width*PLAYER_VIEW_Y; //compute the theorical top left corner
|
|
|
|
int beginline = coo_player_map - PLAYER_VIEW_Y*level_width - coo_player_map%level_width; //index of the tile wich begin the row
|
|
|
|
|
|
|
|
//anti begin oob
|
2021-07-30 02:01:05 +02:00
|
|
|
if(beginmap < 0) {
|
2021-08-04 20:12:53 +02:00
|
|
|
beginmap = game->player->x - PLAYER_VIEW_X;
|
2021-07-30 02:01:05 +02:00
|
|
|
if(beginmap < 0) beginmap = 0;
|
|
|
|
}
|
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
//anti horizontal oob
|
|
|
|
if((coo_player_map - PLAYER_VIEW_X)%level_width > coo_player_map%level_width) {
|
|
|
|
beginmap = beginline > 0 ? beginline : 0;
|
2021-07-30 02:01:05 +02:00
|
|
|
}
|
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
int next = game->player->x + PLAYER_VIEW_X + beginmap/level_width * level_width; //index of the top right corner
|
|
|
|
int endline = beginmap+level_width-beginmap%level_width-1; //index of the tile wich end the row
|
2021-07-30 02:01:05 +02:00
|
|
|
|
|
|
|
if(next > endline) next = endline;
|
2021-08-04 20:12:53 +02:00
|
|
|
if(next < 0) next = game->player->x + PLAYER_VIEW_X;
|
2021-07-30 02:01:05 +02:00
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
int indypro = game->player->y + PLAYER_VIEW_Y; //y value of the bottom row
|
|
|
|
//anti bottom oob
|
|
|
|
if(indypro > taillemap/level_width-1) indypro = taillemap/level_width-1;
|
2021-07-30 02:01:05 +02:00
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
int endmap = next%level_width + level_width*indypro; //index of the bottom right corner
|
|
|
|
int ecart = next - beginmap; //number of column to draw
|
2021-07-30 02:01:05 +02:00
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
//player x, y on the compute map
|
2021-07-30 02:01:05 +02:00
|
|
|
int xcentre = 0, ycentre = 0;
|
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
//calculate the player position in the generated map
|
|
|
|
for(int i = beginmap; i < coo_player_map; i++) {
|
|
|
|
xcentre++;
|
|
|
|
|
|
|
|
if(i == next + ycentre * level_width) {
|
|
|
|
ycentre++;
|
|
|
|
xcentre=0;
|
|
|
|
i = beginmap + ycentre*level_width-1;
|
2021-07-30 02:01:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-04 20:12:53 +02:00
|
|
|
int j = 0;
|
|
|
|
int x = posx-xcentre;
|
2021-07-30 02:01:05 +02:00
|
|
|
for(int i = beginmap; i <= endmap; i++) {
|
2021-08-04 20:12:53 +02:00
|
|
|
int y = j + (posy-ycentre);
|
2021-07-30 02:01:05 +02:00
|
|
|
|
2021-08-19 02:29:51 +02:00
|
|
|
for(int layer = 0; layer < game->map->nb_layers; layer++) {
|
2021-08-18 02:10:31 +02:00
|
|
|
int tile = game->map->layers[layer][i]-1;
|
2021-07-29 18:33:22 +02:00
|
|
|
if(tile != -1) {
|
|
|
|
int tile_x = tile % TILESET_WIDTH;
|
|
|
|
int tile_y = tile / TILESET_WIDTH;
|
2021-08-05 03:12:40 +02:00
|
|
|
dsubimage(x * 16 - game->player->anim.dx * 3, y * 16 - game->player->anim.dy * 3,
|
|
|
|
game->map->tileset, tile_x * 16, tile_y * 16, 16, 16, DIMAGE_NONE);
|
2021-07-29 18:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
2021-07-30 02:01:05 +02:00
|
|
|
|
|
|
|
x++;
|
|
|
|
if(i==beginmap+ecart+j*level_width) {
|
|
|
|
j++;
|
2021-08-04 20:12:53 +02:00
|
|
|
x=posx-xcentre;
|
2021-07-30 02:01:05 +02:00
|
|
|
i = beginmap + j*level_width-1;
|
|
|
|
}
|
2021-07-29 18:33:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-19 02:29:51 +02:00
|
|
|
void engine_draw_map(struct Game const *game) {
|
|
|
|
int x_offset = (game->camera->x - DWIDTH/2);
|
|
|
|
int y_offset = (game->camera->y - DHEIGHT/2);
|
|
|
|
|
|
|
|
//currently -1 to avoid white during transition
|
|
|
|
for (int layer = 0 ; layer < game->map->nb_layers; layer++) {
|
|
|
|
for (int y = -1 ; y <= DHEIGHT / TILE_SIZE + 1; y++) {
|
|
|
|
for (int x = -1 ; x <= DWIDTH / TILE_SIZE + 1; x++) {
|
|
|
|
unsigned int tile_id = 0;
|
|
|
|
if(game->map->w > x && game->map->h > y) {
|
|
|
|
//detect if the map is oob
|
|
|
|
int indexY = (y + y_offset / TILE_SIZE);
|
|
|
|
int indexX = (x + x_offset / TILE_SIZE);
|
|
|
|
if(indexX >= 0 && indexX < game->map->w
|
|
|
|
&& indexY >= 0 && indexY < game->map->h)
|
|
|
|
tile_id = game->map->layers[layer][indexX + indexY * game->map->w];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile_id != 0) {
|
|
|
|
tile_id--;
|
|
|
|
unsigned int tile_x = TILE_SIZE * (tile_id % TILESET_WIDTH);
|
|
|
|
unsigned int tile_y = TILE_SIZE * (tile_id / TILESET_WIDTH);
|
|
|
|
|
|
|
|
//provisoire le temps de trouver une manière propre
|
|
|
|
dsubimage(x * TILE_SIZE - x_offset%TILE_SIZE - game->player->anim.dx * 3,
|
|
|
|
y * TILE_SIZE - y_offset%TILE_SIZE - game->player->anim.dy * 3, game->map->tileset,
|
|
|
|
tile_x, tile_y, TILE_SIZE, TILE_SIZE, DIMAGE_NONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*draw the player*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_draw_player(struct Player const *player) {
|
2021-08-04 20:12:53 +02:00
|
|
|
dframe(player->show_x * 16, player->show_y * 16 - 5, player->anim.img); //draw the player 5 pixel up
|
2021-07-30 02:01:05 +02:00
|
|
|
dprint(1,1,C_BLACK,"%d:%d",player->x, player->y);
|
2021-07-29 18:33:22 +02:00
|
|
|
}
|
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*move the player to the direction*/
|
2021-08-15 03:46:49 +02:00
|
|
|
int engine_move(struct Game *game, int direction) {
|
2021-07-29 18:33:22 +02:00
|
|
|
int dx = (direction == DIR_RIGHT) - (direction == DIR_LEFT);
|
|
|
|
int dy = (direction == DIR_DOWN) - (direction == DIR_UP);
|
|
|
|
|
2021-08-05 03:12:40 +02:00
|
|
|
if(!game->player->idle) return 0;
|
|
|
|
|
2021-07-31 03:40:14 +02:00
|
|
|
if(game->player->direction == direction) {
|
|
|
|
if(map_walkable(game->map, game->player->x + dx, game->player->y + dy)) {
|
|
|
|
game->player->x += dx;
|
|
|
|
game->player->y += dy;
|
2021-08-19 02:29:51 +02:00
|
|
|
|
|
|
|
game->camera->x += dx*16;
|
|
|
|
game->camera->y += dy*16;
|
|
|
|
|
2021-08-05 03:12:40 +02:00
|
|
|
game->player->idle = !anim_player_walking(&game->player->anim, 1);
|
2021-08-15 02:42:26 +02:00
|
|
|
engine_check_position(game);
|
2021-07-31 18:44:06 +02:00
|
|
|
} else {
|
|
|
|
game->player->idle = !anim_player_idle(&game->player->anim, 1);
|
2021-07-31 03:40:14 +02:00
|
|
|
}
|
2021-07-30 02:01:05 +02:00
|
|
|
} else {
|
2021-07-31 03:40:14 +02:00
|
|
|
game->player->direction = direction;
|
2021-07-31 18:44:06 +02:00
|
|
|
game->player->anim.dir = direction;
|
|
|
|
}
|
2021-08-05 03:12:40 +02:00
|
|
|
return 1;
|
2021-07-31 18:44:06 +02:00
|
|
|
}
|
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*update the player animation*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_tick(struct Game *game, int dt) {
|
2021-08-04 20:12:53 +02:00
|
|
|
game->player->anim.duration -= dt;
|
2021-08-19 02:29:51 +02:00
|
|
|
vec_lerp(game->camera, game->player, 0.05);
|
2021-08-04 20:12:53 +02:00
|
|
|
if(game->player->anim.duration <= 0) {
|
|
|
|
game->player->idle = !game->player->anim.function(&game->player->anim, 0);
|
2021-07-30 02:01:05 +02:00
|
|
|
}
|
2021-07-31 03:40:14 +02:00
|
|
|
}
|
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*set the background color*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_set_background(struct Game *game, int color) {
|
2021-08-05 03:12:40 +02:00
|
|
|
game->background = color;
|
2021-08-07 01:49:03 +02:00
|
|
|
}
|
|
|
|
|
2021-08-08 01:43:26 +02:00
|
|
|
/*make an interaction with something*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_action(struct Game const *game, int action) {
|
2021-08-07 01:49:03 +02:00
|
|
|
if(action == ACTION_SHIFT) {
|
|
|
|
if(player_facing(game) == TILE_CHARACTER) {
|
|
|
|
int direction = game->player->direction;
|
|
|
|
int dx = (direction == DIR_RIGHT) - (direction == DIR_LEFT);
|
|
|
|
int dy = (direction == DIR_DOWN) - (direction == DIR_UP);
|
|
|
|
draw_dialog(get_character_xy(game->characters, game->player->x + dx, game->player->y + dy));
|
|
|
|
}
|
|
|
|
}
|
2021-08-15 02:42:26 +02:00
|
|
|
}
|
|
|
|
|
2021-08-15 03:10:05 +02:00
|
|
|
/*check the current position of the player. To perform action depends of his location*/
|
2021-08-15 03:46:49 +02:00
|
|
|
void engine_check_position(struct Game *game) {
|
2021-08-15 02:42:26 +02:00
|
|
|
int player_curr_tile = map_get_player_tile(game);
|
|
|
|
if(player_curr_tile == TILE_DOOR) {
|
|
|
|
engine_set_background(game, C_BLACK);
|
|
|
|
} else {
|
|
|
|
engine_set_background(game, C_WHITE);
|
|
|
|
}
|
2021-08-15 03:46:49 +02:00
|
|
|
}
|
2021-08-19 02:29:51 +02:00
|
|
|
|
|
|
|
void vec_lerp(struct Camera *from, struct Player const *to, float scale) {
|
|
|
|
from->x = from->x * (1 - scale) + (to->x*TILE_SIZE + to->x_mid) * scale;
|
|
|
|
from->y = from->y * (1 - scale) + (to->y*TILE_SIZE + to->y_mid) * scale;
|
|
|
|
}
|