175 lines
4.9 KiB
C
175 lines
4.9 KiB
C
// Copyright 2025 Bill Rossi
|
|
//
|
|
// This file is part of Hanafuda Hachi-Hachi.
|
|
//
|
|
// Hanafuda Hachi-Hachi is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
//
|
|
// Hanafuda Hachi-Hachi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with Hanafuda Hachi-Hachi. If not, see <https://www.gnu.org/licenses/>.
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "card.h"
|
|
|
|
static Vector2 card_size = (Vector2) { CARD_WIDTH, CARD_HEIGHT };
|
|
static char *month_english_abbr[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
|
|
|
Color BRICKRED = (Color) { 136, 12, 2, 255 };
|
|
void draw_card(Card *c, Texture2D *cards_texture, int index) {
|
|
int i_vert = c->index % 4;
|
|
int i_horiz = c->index / 4;
|
|
int pos_vert = i_vert * CARD_HEIGHT;
|
|
int pos_horiz = i_horiz * CARD_WIDTH;
|
|
|
|
Color color = index == 1 ? BLACK : BRICKRED;
|
|
|
|
if (c->selected) {
|
|
DrawRectangleRec((Rectangle) { c->position.x - 6, c->position.y - 6, card_size.x + 12, card_size.y + 12 }, BLUE);
|
|
}
|
|
|
|
if (c->visible) {
|
|
DrawTexturePro(
|
|
*cards_texture,
|
|
(Rectangle) { pos_horiz, pos_vert, CARD_WIDTH, CARD_HEIGHT },
|
|
(Rectangle) { c->position.x, c->position.y, card_size.x, card_size.y },
|
|
(Vector2) { 0, 0 },
|
|
0.,
|
|
RAYWHITE
|
|
);
|
|
} else {
|
|
DrawRectangleRec((Rectangle) { c->position.x, c->position.y, card_size.x, card_size.y }, color);
|
|
}
|
|
|
|
}
|
|
|
|
bool point_within_card(Card *c, Vector2 point) {
|
|
return point.x > c->position.x && point.x < c->position.x + card_size.x &&
|
|
point.y > c->position.y && point.y < c->position.y + card_size.y;
|
|
}
|
|
|
|
void shuffle_hand(Hand *h) {
|
|
Card *swap;
|
|
for (int i = h->count - 1; i >= 0; i--) {
|
|
int index = rand() % (i + 1);
|
|
swap = h->cards[i];
|
|
h->cards[i] = h->cards[index];
|
|
h->cards[index] = swap;
|
|
}
|
|
}
|
|
|
|
void order_deck(Hand *h) {
|
|
Card *swap;
|
|
|
|
swap = h->cards[1];
|
|
h->cards[1] = h->cards[47-0];
|
|
h->cards[47-0] = swap;
|
|
|
|
swap = h->cards[5];
|
|
h->cards[5] = h->cards[47-1];
|
|
h->cards[47-1] = swap;
|
|
|
|
swap = h->cards[9];
|
|
h->cards[9] = h->cards[47-2];
|
|
h->cards[47-2] = swap;
|
|
|
|
swap = h->cards[0];
|
|
h->cards[0] = h->cards[47-12];
|
|
h->cards[47-12] = swap;
|
|
|
|
swap = h->cards[4];
|
|
h->cards[4] = h->cards[47-13];
|
|
h->cards[47-13] = swap;
|
|
|
|
swap = h->cards[8];
|
|
h->cards[8] = h->cards[47-14];
|
|
h->cards[47-14] = swap;
|
|
}
|
|
|
|
void remove_from_hand(Hand *h, Card *c) {
|
|
c->selected = false;
|
|
bool card_found = false;
|
|
for (int i = 0; i < h->count - 1; i++) {
|
|
if (h->cards[i] == c) card_found = true;
|
|
if (card_found) h->cards[i] = h->cards[i + 1];
|
|
}
|
|
h->count--;
|
|
}
|
|
|
|
int first_open_spot(Hand *h) {
|
|
int order_guy[48];
|
|
int order_guy_count = 0;
|
|
|
|
for (int i = 0; i < 48; i++) {
|
|
order_guy[i] = 0;
|
|
}
|
|
|
|
for (int i = 0; i < h->count; i++) {
|
|
if (h->cards[i] == NULL) continue;
|
|
order_guy[h->cards[i]->order] = 1;
|
|
order_guy_count++;
|
|
}
|
|
|
|
int fos = h->count;
|
|
for (int i = 0; i < order_guy_count; i++) {
|
|
if (order_guy[i]) continue;
|
|
fos = i;
|
|
break;
|
|
}
|
|
return fos;
|
|
}
|
|
|
|
void add_to_hand(Hand *h, Card *c, float deal_speed) {
|
|
c->order = first_open_spot(h);
|
|
h->cards[h->count] = c;
|
|
|
|
c->move.position = &c->position;
|
|
c->move.origin.x = c->position.x;
|
|
c->move.origin.y = c->position.y;
|
|
switch (h->display_type) {
|
|
case HAND_DISPLAY_ROW:
|
|
c->move.destination.x = h->position.x + (c->order * (CARD_WIDTH + 10));
|
|
c->move.destination.y = h->position.y;
|
|
break;
|
|
case HAND_DISPLAY_FIELD:
|
|
c->move.destination.x = h->position.x + ((c->order / 2) * (CARD_WIDTH + 10));
|
|
c->move.destination.y = h->position.y + (c->order % 2 * (CARD_HEIGHT + 10));
|
|
break;
|
|
case HAND_DISPLAY_DECK:
|
|
c->move.destination.x = h->position.x;
|
|
c->move.destination.y = h->position.y;
|
|
break;
|
|
case HAND_DISPLAY_SCORED:
|
|
c->move.destination.x = h->position.x + (c->order * (CARD_WIDTH - 30));
|
|
c->move.destination.y = h->position.y;
|
|
break;
|
|
}
|
|
c->move.curve = CURVE_EASE_IN_OUT;
|
|
c->move.current_time = 0.;
|
|
c->move.end_time = deal_speed;
|
|
|
|
h->count++;
|
|
}
|
|
|
|
bool card_done_moving(Card *c) {
|
|
return c->move.current_time > c->move.end_time;
|
|
}
|
|
|
|
void deal(Hand *from, Hand *to, int count, bool up, float deal_speed) {
|
|
for (int i = 0; i < count; i++) {
|
|
Card *c = from->cards[from->count - 1];
|
|
c->visible = up;
|
|
add_to_hand(to, c, deal_speed);
|
|
from->count--;
|
|
}
|
|
}
|
|
|
|
Rectangle next_card_position(Hand *h) {
|
|
int i = first_open_spot(h);
|
|
return (Rectangle) {
|
|
h->position.x + ((i / 2) * (CARD_WIDTH + 10)),
|
|
h->position.y + (i % 2 * (CARD_HEIGHT + 10)),
|
|
CARD_WIDTH,
|
|
CARD_HEIGHT
|
|
};
|
|
}
|