2514 ALLEGRO_BITMAP** overlay_bitmaps,
2515 int num_overlay_tiles,
2527 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2532 float phw = hw0 * zoom;
2533 float phh = hh0 * zoom;
2534 float lift = tl0 * zoom;
2535 float tile_draw_w = 2.0f * phw;
2536 float tile_draw_h = 2.0f * phh;
2552 if (!draw_order)
return;
2557 int obj_order_buf[64];
2558 int* obj_order = NULL;
2559 float* obj_sx_arr = NULL;
2560 float* obj_sy_arr = NULL;
2561 int nobj = (objects && num_objects > 0) ? num_objects : 0;
2564 obj_order = (nobj <= 64) ? obj_order_buf : (
int*)malloc((
size_t)nobj *
sizeof(int));
2565 obj_sx_arr = (
float*)malloc((
size_t)nobj *
sizeof(float));
2566 obj_sy_arr = (
float*)malloc((
size_t)nobj *
sizeof(float));
2568 if (!obj_order || !obj_sx_arr || !obj_sy_arr) {
2569 n_log(
LOG_ERR,
"iso_map_draw: object allocation failed");
2570 if (obj_order && obj_order != obj_order_buf) free(obj_order);
2571 if (obj_sx_arr) free(obj_sx_arr);
2572 if (obj_sy_arr) free(obj_sy_arr);
2581 for (
int i = 0; i < nobj; i++) {
2587 obj_sx_arr[i] = wsx * zoom + cam_px;
2588 obj_sy_arr[i] = wsy * zoom + cam_py;
2592 for (
int i = 1; i < nobj; i++) {
2593 int key = obj_order[i];
2594 int key_fz = (int)floorf(objects[
key].fz);
2595 int key_my = (int)floorf(objects[
key].fy);
2596 int key_mx = (int)floorf(objects[
key].fx);
2597 int key_depth = key_my + key_mx;
2600 int cj = obj_order[j];
2601 int cj_fz = (int)floorf(objects[cj].fz);
2602 int cj_my = (int)floorf(objects[cj].fy);
2603 int cj_mx = (int)floorf(objects[cj].fx);
2604 int cj_depth = cj_my + cj_mx;
2605 if (cj_depth > key_depth ||
2606 (cj_depth == key_depth && cj_fz > key_fz) ||
2607 (cj_depth == key_depth && cj_fz == key_fz && cj_my > key_my) ||
2608 (cj_depth == key_depth && cj_fz == key_fz && cj_my == key_my && cj_mx > key_mx)) {
2609 obj_order[j + 1] = obj_order[j];
2615 obj_order[j + 1] =
key;
2621 for (
int di = 0; di < num_entries; di++) {
2622 if (draw_order[di].bottom > 0)
continue;
2624 int mx = draw_order[di].
mx;
2625 int my = draw_order[di].
my;
2626 int seg_top = draw_order[di].
top;
2631 int top_terrain = base;
2632 int wall_terrain = base;
2634 int si = draw_order[di].
seg_idx;
2635 int tidx = my * map->
width + mx;
2636 if (map->
segments && tidx >= 0 && tidx < map->width * map->
height &&
2637 si >= 0 && si < map->segments[tidx].count) {
2640 if (ut >= 0 && ut < map->num_terrains) top_terrain = ut;
2641 if (lt >= 0 && lt < map->num_terrains) wall_terrain = lt;
2646 float base_dx, base_dy;
2649 float h_n, h_e, h_s, h_w;
2651 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, h_n, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2652 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, h_e, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2653 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, h_s, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2654 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, h_w, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2658 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, (
float)h, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2659 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)h, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2660 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2661 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2667 float min_vy = fminf(fminf(vy[0], vy[1]), fminf(vy[2], vy[3]));
2668 float max_vy = fmaxf(fmaxf(vy[0], vy[1]), fmaxf(vy[2], vy[3]));
2669 float max_side = fmaxf((
float)h, (
float)map->
max_height) * lift;
2670 if (vx[1] < 0 || vx[3] > (
float)
screen_w)
continue;
2671 if (max_vy + max_side < 0 || min_vy > (
float)
screen_h)
continue;
2677 float dyn_r = 0.0f, dyn_g = 0.0f, dyn_b = 0.0f;
2679 int lidx = (my * map->
width + mx) * 3;
2686 amb_r, amb_g, amb_b,
2687 dyn_r, dyn_g, dyn_b);
2688 float seg_brightness = 1.0f;
2690 float ratio = (float)seg_top / (
float)map->
max_height;
2694 seg_brightness *= (amb_r + amb_g + amb_b) / 3.0f;
2695 float wall_dyn = (dyn_r + dyn_g + dyn_b) / 3.0f;
2696 seg_brightness += wall_dyn;
2697 if (seg_brightness > 1.0f) seg_brightness = 1.0f;
2700 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2704 al_draw_tinted_scaled_bitmap(
tile_bitmaps[top_terrain], seg_tint,
2705 0, 0, (
float)tile_w, (
float)tile_h,
2706 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2718 float ce_x, ce_y, cs_x, cs_y, cw_x, cw_y;
2719 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)h, cam_px, cam_py, zoom, &ce_x, &ce_y);
2720 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)h, cam_px, cam_py, zoom, &cs_x, &cs_y);
2721 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)h, cam_px, cam_py, zoom, &cw_x, &cw_y);
2723 mx, my, 0, seg_top, lift, seg_brightness, wall_terrain);
2727 mx, my, 0, seg_top, lift, seg_brightness, wall_terrain);
2733 int edge_bits_arr[16];
2734 int corner_bits_arr[16];
2736 memset(edge_bits_arr, 0,
sizeof(
int) * (
size_t)nt);
2737 memset(corner_bits_arr, 0,
sizeof(
int) * (
size_t)nt);
2740 for (
int t = base + 1; t < nt; t++) {
2743 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2746 vx, vy, tile_w, tile_h, seg_tint);
2750 0, 0, (
float)tile_w, (
float)tile_h,
2751 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2755 int cidx = num_edge_masks + corner_bits_arr[t];
2756 if (corner_bits_arr[t] != 0 && cidx < num_masks &&
2758 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2761 vx, vy, tile_w, tile_h, seg_tint);
2765 0, 0, (
float)tile_w, (
float)tile_h,
2766 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2773 if (overlay_bitmaps && map->
overlay && num_overlay_tiles > 0) {
2774 int ov_idx = my * map->
width + mx;
2775 int ov_tile = map->
overlay[ov_idx];
2776 if (ov_tile > 0 && ov_tile < num_overlay_tiles && overlay_bitmaps[ov_tile]) {
2777 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2781 al_draw_tinted_scaled_bitmap(overlay_bitmaps[ov_tile], seg_tint,
2782 0, 0, (
float)tile_w, (
float)tile_h,
2783 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2790 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2793 draw_order[di].underside,
2799 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2801 ? al_map_rgba(100, 255, 100, 120)
2802 : al_map_rgba(255, 255, 100, 120);
2803 float verts[8] = {vx[0], vy[0], vx[1], vy[1],
2804 vx[2], vy[2], vx[3], vy[3]};
2805 al_draw_filled_polygon(verts, 4, hc);
2807 ? al_map_rgba(100, 255, 100, 200)
2808 : al_map_rgba(255, 255, 100, 200);
2809 al_draw_line(vx[0], vy[0], vx[1], vy[1], oc, 1.5f);
2810 al_draw_line(vx[1], vy[1], vx[2], vy[2], oc, 1.5f);
2811 al_draw_line(vx[2], vy[2], vx[3], vy[3], oc, 1.5f);
2812 al_draw_line(vx[3], vy[3], vx[0], vy[0], oc, 1.5f);
2817 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2818 ALLEGRO_COLOR gc = al_map_rgba(255, 255, 255, 60);
2819 al_draw_line(vx[0], vy[0], vx[1], vy[1], gc, 1.0f);
2820 al_draw_line(vx[1], vy[1], vx[2], vy[2], gc, 1.0f);
2821 al_draw_line(vx[2], vy[2], vx[3], vy[3], gc, 1.0f);
2822 al_draw_line(vx[3], vy[3], vx[0], vy[0], gc, 1.0f);
2825 ALLEGRO_COLOR hc2 = al_map_rgba(255, 200, 100,
2826 (
unsigned char)(60 + h * 35));
2827 float dot_x = (vx[0] + vx[2]) / 2.0f;
2828 float dot_y = (vy[0] + vy[1] + vy[2] + vy[3]) / 4.0f;
2829 al_draw_filled_circle(dot_x, dot_y, 2.0f * zoom, hc2);
2840 for (
int di = 0; di < num_entries; di++) {
2841 int mx = draw_order[di].
mx;
2842 int my = draw_order[di].
my;
2843 int seg_bottom = draw_order[di].
bottom;
2849 int seg_depth = my + mx;
2850 while (obj_cursor < nobj) {
2851 int oi = obj_order[obj_cursor];
2852 int obj_fz = (int)floorf(objects[oi].fz);
2853 int obj_my = (int)floorf(objects[oi].fy);
2854 int obj_mx = (int)floorf(objects[oi].fx);
2855 int obj_depth = obj_my + obj_mx;
2856 if (obj_depth > seg_depth ||
2857 (obj_depth == seg_depth && obj_fz > seg_bottom) ||
2858 (obj_depth == seg_depth && obj_fz == seg_bottom && obj_my > my) ||
2859 (obj_depth == seg_depth && obj_fz == seg_bottom && obj_my == my && obj_mx >= mx))
2861 if (objects[oi].draw) {
2862 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
2863 zoom, 1.0f, objects[oi].user_data);
2870 if (seg_bottom == 0)
continue;
2873 int seg_top = draw_order[di].
top;
2878 int etop_terrain = base;
2879 int ewall_terrain = base;
2881 int si = draw_order[di].
seg_idx;
2882 int tidx = my * map->
width + mx;
2883 if (map->
segments && tidx >= 0 && tidx < map->width * map->
height &&
2884 si >= 0 && si < map->segments[tidx].count) {
2887 if (ut >= 0 && ut < map->num_terrains) etop_terrain = ut;
2888 if (lt >= 0 && lt < map->num_terrains) ewall_terrain = lt;
2893 float base_dx, base_dy;
2894 _iso_corner_to_screen(hw0, hh0, tl0, mx, my, (
float)h, cam_px, cam_py, zoom, &vx[0], &vy[0]);
2895 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my, (
float)h, cam_px, cam_py, zoom, &vx[1], &vy[1]);
2896 _iso_corner_to_screen(hw0, hh0, tl0, mx + 1, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[2], &vy[2]);
2897 _iso_corner_to_screen(hw0, hh0, tl0, mx, my + 1, (
float)h, cam_px, cam_py, zoom, &vx[3], &vy[3]);
2902 float min_vy = fminf(fminf(vy[0], vy[1]), fminf(vy[2], vy[3]));
2903 float max_vy = fmaxf(fmaxf(vy[0], vy[1]), fmaxf(vy[2], vy[3]));
2904 float max_side = fmaxf((
float)h, (
float)map->
max_height) * lift;
2905 if (vx[1] < 0 || vx[3] > (
float)
screen_w)
continue;
2906 if (max_vy + max_side < 0 || min_vy > (
float)
screen_h)
continue;
2909 if (draw_order[di].underside &&
tile_bitmaps[etop_terrain]) {
2910 float under_sx, under_sy;
2912 float under_dx = under_sx * zoom + cam_px;
2913 float under_dy = under_sy * zoom + cam_py;
2915 phw, phh, tile_draw_w, tile_draw_h,
2924 float edyn_r = 0.0f, edyn_g = 0.0f, edyn_b = 0.0f;
2926 int elidx = (my * map->
width + mx) * 3;
2933 eamb_r, eamb_g, eamb_b,
2934 edyn_r, edyn_g, edyn_b);
2935 float eseg_brightness = 1.0f;
2937 float ratio = (float)seg_top / (
float)map->
max_height;
2940 eseg_brightness *= (eamb_r + eamb_g + eamb_b) / 3.0f;
2941 eseg_brightness += (edyn_r + edyn_g + edyn_b) / 3.0f;
2942 if (eseg_brightness > 1.0f) eseg_brightness = 1.0f;
2945 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
2946 al_draw_tinted_scaled_bitmap(
tile_bitmaps[etop_terrain], eseg_tint,
2947 0, 0, (
float)tile_w, (
float)tile_h,
2948 base_dx, base_dy, tile_draw_w, tile_draw_h, 0);
2951 if (seg_top > seg_bottom) {
2953 mx, my, seg_bottom, seg_top, lift, eseg_brightness, ewall_terrain);
2954 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2956 seg_bottom, seg_top,
2957 draw_order[di].underside,
2963 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2965 ? al_map_rgba(100, 255, 100, 120)
2966 : al_map_rgba(255, 255, 100, 120);
2967 float verts[8] = {vx[0], vy[0], vx[1], vy[1],
2968 vx[2], vy[2], vx[3], vy[3]};
2969 al_draw_filled_polygon(verts, 4, hc);
2971 ? al_map_rgba(100, 255, 100, 200)
2972 : al_map_rgba(255, 255, 100, 200);
2973 al_draw_line(vx[0], vy[0], vx[1], vy[1], oc, 1.5f);
2974 al_draw_line(vx[1], vy[1], vx[2], vy[2], oc, 1.5f);
2975 al_draw_line(vx[2], vy[2], vx[3], vy[3], oc, 1.5f);
2976 al_draw_line(vx[3], vy[3], vx[0], vy[0], oc, 1.5f);
2981 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
2982 ALLEGRO_COLOR gc = al_map_rgba(255, 255, 255, 60);
2983 al_draw_line(vx[0], vy[0], vx[1], vy[1], gc, 1.0f);
2984 al_draw_line(vx[1], vy[1], vx[2], vy[2], gc, 1.0f);
2985 al_draw_line(vx[2], vy[2], vx[3], vy[3], gc, 1.0f);
2986 al_draw_line(vx[3], vy[3], vx[0], vy[0], gc, 1.0f);
2989 ALLEGRO_COLOR hc2 = al_map_rgba(255, 200, 100,
2990 (
unsigned char)(60 + h * 35));
2991 float dot_x = (vx[0] + vx[2]) / 2.0f;
2992 float dot_y = (vy[0] + vy[1] + vy[2] + vy[3]) / 4.0f;
2993 al_draw_filled_circle(dot_x, dot_y, 2.0f * zoom, hc2);
2999 while (obj_cursor < nobj) {
3000 int oi = obj_order[obj_cursor];
3001 if (objects[oi].draw) {
3002 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
3003 zoom, 1.0f, objects[oi].user_data);
3011 for (
int i = 0; i < nobj; i++) {
3012 int oi = obj_order[i];
3013 if (objects[oi].occluded_alpha <= 0.0f)
continue;
3014 if (!objects[oi].draw)
continue;
3016 float clip_y = 1e9f;
3018 objects[oi].fx, objects[oi].fy, objects[oi].fz,
3019 obj_sx_arr[oi], obj_sy_arr[oi],
3020 objects[oi].sprite_h,
3021 objects[oi].sprite_half_w,
3022 cam_px, cam_py, zoom,
3030 int prev_cx, prev_cy, prev_cw, prev_ch;
3031 al_get_clipping_rectangle(&prev_cx, &prev_cy, &prev_cw, &prev_ch);
3032 int clip_top = (int)floorf(clip_y);
3033 if (clip_top < prev_cy) clip_top = prev_cy;
3034 al_set_clipping_rectangle(prev_cx, clip_top,
3035 prev_cw, prev_cy + prev_ch - clip_top);
3036 objects[oi].
draw(obj_sx_arr[oi], obj_sy_arr[oi],
3037 zoom, objects[oi].occluded_alpha, objects[oi].user_data);
3038 al_set_clipping_rectangle(prev_cx, prev_cy, prev_cw, prev_ch);
3043 if (obj_order && obj_order != obj_order_buf) free(obj_order);
3044 if (obj_sx_arr) free(obj_sx_arr);
3045 if (obj_sy_arr) free(obj_sy_arr);