You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
258 lines
9.0 KiB
258 lines
9.0 KiB
#include "isometricMap.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "tile.h"
|
|
#include "raymath.h"
|
|
#include "raylib.h"
|
|
#include "../DepthSorting/bucket.h"
|
|
#include "../game.h"
|
|
#include "../List/list.h"
|
|
#include "../DepthSorting/mergeSort.h"
|
|
|
|
// returns pointer to IsometricMap Instance
|
|
IsometricMap * IsometricMapInit(int layer){
|
|
IsometricMap* map = (IsometricMap *) malloc(sizeof(IsometricMap));
|
|
|
|
map->tileTextures[0] = LoadTexture("assets/grass.png");
|
|
map->tileTextures[1] = LoadTexture("assets/grass_selected.png");
|
|
map->tileTextures[2] = LoadTexture("assets/tower.png");
|
|
|
|
//map->tileTextures[0] = LoadTexture("assets/desert.png");
|
|
//map->tileTextures[1] = LoadTexture("assets/bigtower.png");
|
|
|
|
map->width = 500;
|
|
map->height = 500;
|
|
map->textureWidth = map->tileTextures[0].width;
|
|
map->textureHeight = map->tileTextures[0].height;
|
|
map->worldPixelWidth = map->width * map->textureWidth;
|
|
map->worldPixelWidth = map->height * map->textureHeight;
|
|
map->layer = layer;
|
|
|
|
|
|
// mallocating the twodimensional Tiles Array
|
|
Tile*** tiles = (Tile***)malloc(map->width*sizeof(Tile*));
|
|
int n = 0;
|
|
for(n=0; n < map->width; n++){
|
|
tiles[n] = (Tile**)malloc(map->height*sizeof(Tile*));
|
|
}
|
|
|
|
int i = 0;
|
|
int j = 0;
|
|
int quarterTextureSize = map->textureWidth / 4;
|
|
int halfTextureSize = map->textureWidth / 2;
|
|
for(i=0; i < map->width; i++){
|
|
for(j=0; j < map->height; j++){
|
|
Tile *tmp = (Tile *) malloc(sizeof(Tile));
|
|
// initially all the Tiles are "empty"
|
|
tmp->textureId = -1;
|
|
tmp->x = i;
|
|
tmp->y = j;
|
|
tmp->z = layer;
|
|
|
|
Vector2 *offset = IsometricMapCalcOffsetForTileAtEfficient(i,j, halfTextureSize, quarterTextureSize);
|
|
// the higher the layer the higher it needs to be drawed
|
|
offset->y -= layer * quarterTextureSize;
|
|
tmp->offsetX = offset->x;
|
|
tmp->offsetY = offset->y;
|
|
free(offset);
|
|
tmp->sortable = BucketInit(0, tmp);
|
|
tiles[i][j] = tmp;
|
|
}
|
|
}
|
|
|
|
map->tiles = tiles;
|
|
|
|
return map;
|
|
}
|
|
|
|
// For Rendering: calculates coordinate offset for a single tile at arrayPosition x y
|
|
// Only works for tiles with texture width == height (and for 22.5 degree?)
|
|
Vector2 * IsometricMapCalcOffsetForTileAt(int x, int y, int textureSize){
|
|
Vector2* offset = (Vector2 *)malloc(sizeof(Vector2));
|
|
offset->x = x * textureSize/2 - y * textureSize/2;
|
|
offset->y = x * textureSize/4 + y * textureSize/4;
|
|
return offset;
|
|
}
|
|
|
|
Vector2 * IsometricMapCalcOffsetForTileAtEfficient(int x, int y, int halfTextureSize, int quarterTextureSize){
|
|
Vector2* offset = (Vector2 *)malloc(sizeof(Vector2));
|
|
offset->x = x * halfTextureSize - y * halfTextureSize;
|
|
offset->y = x * quarterTextureSize + y * quarterTextureSize;
|
|
return offset;
|
|
}
|
|
|
|
// returns Tile at x y on layer isometricMap
|
|
Tile * IsometricMapGetTileFromArrayPosition(IsometricMap *map, int x, int y){
|
|
return map->tiles[x][y];
|
|
}
|
|
|
|
// Unproject: World Coordinates -> Screen Coordinates writes result in tmp Vector
|
|
void IsometricMapProject(IsometricMap *isometricMap, Camera2D *camera, float x, float y, Vector2 *tmp){
|
|
|
|
float tileWidthHalf = isometricMap->textureWidth / 2;
|
|
float tileHeightQuarter = isometricMap->textureHeight / 4;
|
|
|
|
x += camera->target.x;
|
|
y += camera->target.y;
|
|
|
|
float xPos = (float) x;
|
|
float yPos = (float) y;
|
|
|
|
float isoX = 0.5 * ( xPos / tileWidthHalf + yPos / tileHeightQuarter);
|
|
float isoY = 0.5 * ( -xPos / tileWidthHalf + yPos / tileHeightQuarter);
|
|
|
|
tmp->x = isoX * isometricMap->tileTextures[0].width;
|
|
tmp->y = isoY * isometricMap->tileTextures[0].height;
|
|
}
|
|
|
|
// Unproject: World Coordinates -> Screen Coordinates writes result in tmp Vector
|
|
void IsometricMapUnproject(IsometricMap **isometricMap, Camera2D *camera, int x, int y, float z, Vector2 *tmp){
|
|
float xPos = (float) x;
|
|
float yPos = (float) y;
|
|
|
|
float screenX = (xPos - yPos) / 2;
|
|
float screenY = (xPos + yPos) / 4;
|
|
|
|
screenX += camera->target.x;
|
|
screenY += camera->target.y;
|
|
|
|
// z is currently implemented as z=1 equals 1 layer, z=2 would be two layers height (could be smoothed)
|
|
// hardcoded tile height
|
|
screenY -= z * 10;
|
|
|
|
tmp->x = screenX;
|
|
tmp->y = screenY;
|
|
}
|
|
|
|
// returns Tile * -> tile at coordinates x y z=layer
|
|
Tile * IsometricMapGetTileFromWorldCoordinates(IsometricMap **isometricMap, float x, float y, float z){
|
|
|
|
int layer = (int) z;
|
|
|
|
x = (int)(x / isometricMap[layer]->textureWidth);
|
|
y = (int)(y / isometricMap[layer]->textureHeight);
|
|
|
|
if( x < isometricMap[layer]->width && y < isometricMap[layer]->height && x >= 0 && y >= 0 ){
|
|
if(isometricMap[layer]->tiles[(int)x][(int)y]->textureId != -1){
|
|
return (isometricMap[layer]->tiles[(int)x][(int)y]);
|
|
}
|
|
}
|
|
Tile *ptr = 0;
|
|
return ptr;
|
|
}
|
|
|
|
// Gives the most upper Tile above *tile
|
|
Tile * IsometricMapGetMostUpperTile(IsometricMap **isometricMap, Tile *tile){
|
|
//Tile *ptr = (Tile *) malloc(sizeof(Tile *));
|
|
// hardcoded layer amount
|
|
int n = 9;
|
|
for(n=9;n>=0;n--){
|
|
if( tile->x < isometricMap[n]->width && tile->y < isometricMap[n]->height &&
|
|
tile->x >= 0 && tile->y >= 0 ){
|
|
if(isometricMap[n]->tiles[tile->x][tile->y]->textureId != -1){
|
|
return isometricMap[n]->tiles[tile->x][tile->y];
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// changes to Texture ID of tile at x y on maplayer layer
|
|
void IsometricMapChangeTextureIdOfTile(IsometricMap **map, int x, int y, int layer, int id){
|
|
if( x < map[layer]->width && y < map[layer]->height &&
|
|
x >= 0 && y >= 0 ){
|
|
(map[layer]->tiles[x][y])->textureId = id;
|
|
}
|
|
else{
|
|
printf("WARNING: trying to change Texture of Tile which is out of bounds!\n");
|
|
}
|
|
}
|
|
|
|
void IsometricMapDraw(Game *game){
|
|
// TODO: Implement as List
|
|
Bucket *buckets[100000];
|
|
int counter = 0;
|
|
|
|
int windowWidth = GetScreenWidth();
|
|
int windowHeight = GetScreenHeight();
|
|
Vector2 topleft = {0, 0};
|
|
IsometricMapProject(game->layers[0], game->camera, topleft.x, topleft.y, &topleft);
|
|
Vector2 topright = {windowWidth, 0};
|
|
IsometricMapProject(game->layers[0], game->camera, topright.x, topright.y, &topright);
|
|
Vector2 botleft = {0, windowHeight};
|
|
IsometricMapProject(game->layers[0], game->camera, botleft.x, botleft.y, &botleft);
|
|
Vector2 botright = {windowWidth, windowHeight};
|
|
IsometricMapProject(game->layers[0], game->camera, botright.x, botright.y, &botright);
|
|
|
|
int extraTiles = 1;
|
|
int n = 0;
|
|
int itmp = (int)(topleft.x / game->layers[0]->textureWidth) - extraTiles;
|
|
int jtmp = (int)(topright.y / game->layers[0]->textureHeight) - extraTiles;
|
|
int maxI = (int)(botright.x / game->layers[0]->textureWidth) + extraTiles;
|
|
int maxJ = (int)(botleft.y / game->layers[0]->textureHeight) + extraTiles;
|
|
if (itmp < 0){ itmp = 0; }
|
|
if (jtmp < 0){ jtmp = 0; }
|
|
if (maxI > game->layers[0]->width){ maxI = game->layers[0]->width; }
|
|
if (maxJ > game->layers[0]->height){ maxJ = game->layers[0]->height; }
|
|
int i, j = 0;
|
|
for (n = 0; n < 10; n++){
|
|
for (j = jtmp; j < maxJ; j++){
|
|
for (i = itmp; i < maxI; i++){
|
|
if (game->layers[n]->tiles[i][j]->textureId == -1){
|
|
}
|
|
else{
|
|
buckets[counter] = game->layers[n]->tiles[i][j]->sortable;
|
|
++counter;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//printf("\n\n\n");
|
|
|
|
Node *current = game->sprites->head;
|
|
int extraPixels = 0;
|
|
// drawing some extra corner pixels
|
|
// if extraPixels == 0 you can see flickering in the corners
|
|
itmp = (int)(topleft.x) - extraPixels;
|
|
jtmp = (int)(topright.y) - extraPixels;
|
|
maxI = (int)(botright.x) + extraPixels;
|
|
maxJ = (int)(botleft.y) + extraPixels;
|
|
while(current != 0){
|
|
// Only drawing the Sprites which are within Camera view
|
|
if( current->data->x > itmp &&
|
|
current->data->y > jtmp &&
|
|
current->data->x < maxI &&
|
|
current->data->y < maxJ){
|
|
buckets[counter] = current->data->sortable;
|
|
++counter;
|
|
}
|
|
current = current->next;
|
|
}
|
|
|
|
int hmmm = counter;
|
|
// Merge Sort ist scuffed
|
|
MergeSort(buckets, hmmm);
|
|
|
|
//printf("HÄÄÄÄÄÄ\n");
|
|
int k = 0;
|
|
for(k = 0; k < counter; k++){
|
|
if(buckets[k]->type == 1){
|
|
//printf("Tile begin -");
|
|
//printf("Tile %f\n", buckets[k]->depth);
|
|
DrawTexture(
|
|
game->layers[0]->tileTextures[buckets[k]->tile->textureId],
|
|
buckets[k]->tile->offsetX,
|
|
buckets[k]->tile->offsetY,
|
|
WHITE);
|
|
//printf("- Tile end \n");
|
|
}
|
|
else if(buckets[k]->type == 0){
|
|
//printf("Sprite %f\n", buckets[k]->depth);
|
|
DrawSpriteToWorld(buckets[k]->sprite, game->layers, game->camera);
|
|
//printf("- Sprite end \n");
|
|
}
|
|
}
|
|
//printf("\n\n");
|
|
|
|
|
|
} |