hanafuda/card.c
2025-02-26 20:05:31 -05:00

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