aboutsummaryrefslogtreecommitdiff
path: root/item.c
diff options
context:
space:
mode:
authorJuan Marín Noguera <juan.marinn@um.es>2019-06-27 20:25:01 +0200
committerJuan Marín Noguera <juan.marinn@um.es>2019-06-27 20:25:01 +0200
commit3228fe41df5fc737efe3ddfde26d6983619458e8 (patch)
tree7e6f79f9866a59eb4028dc57ca0c8bcebf8ed0d4 /item.c
Real initial commit
Diffstat (limited to 'item.c')
-rw-r--r--item.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/item.c b/item.c
new file mode 100644
index 0000000..1bcd3ec
--- /dev/null
+++ b/item.c
@@ -0,0 +1,296 @@
+/*
+ * item.c -- Implementa los objetos (y enemigos) que aparecen en el juego.
+ * Copyright (C) 2018 Juan Marín Noguera
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#include <malloc.h>
+#include <stdlib.h>
+#include "block.h"
+#include "collision_type.h"
+#include "error.h"
+#include "item.h"
+#include "player.h"
+#include "screen.h"
+
+#define ITEM_GRAVITY 0.15
+#define ITEM_VELOCITY_X 1.2
+#define ITEM_KOOPA_MAX_STILL 300
+#define ITEM_TEMPCOIN_LIFETIME 5
+#define ITEM_ANIM_TICKS 3
+#define ITEM_ANIM_X_SHIFT 16
+#define ITEM_GOOMBA_ANIM_NO 2
+#define ITEM_KOOPA_ANIM_NO 4
+#define ITEM_FLOWER_ANIM_NO 4
+
+#define ITEM_GOOMBA_X 0
+#define ITEM_GOOMBA_Y 16
+#define ITEM_GOOMBA_W 16
+#define ITEM_GOOMBA_H 16
+#define ITEM_KOOPA_GROUND_X 160
+#define ITEM_KOOPA_GROUND_Y 24
+#define ITEM_KOOPA_GROUND_W 16
+#define ITEM_KOOPA_GROUND_H 8
+#define ITEM_KOOPA_X 96
+#define ITEM_KOOPA_Y 10
+#define ITEM_KOOPA_W 15
+#define ITEM_KOOPA_H 22
+#define ITEM_MUSHROOM_X 0
+#define ITEM_MUSHROOM_Y 0
+#define ITEM_FLOWER_X 0
+#define ITEM_FLOWER_Y 32
+#define ITEM_COIN_X 0
+#define ITEM_COIN_Y 96
+#define ITEM_UPGRADE_W 16
+#define ITEM_UPGRADE_H 16
+
+#define ITEM_ENEMIES_FILE "52570.bmp"
+#define ITEM_UPGRADES_FILE "52569.bmp"
+
+struct Item {
+ ItemType type;
+ int dir;
+ int cnt;
+ double x;
+ double y;
+ double vy;
+};
+
+Picture item_enemies_pict = NULL, item_upgrades_pict = NULL;
+
+Item item_create(ItemType type, double x, double y)
+{
+ Item i = malloc(sizeof(struct Item));
+
+ if (i == NULL)
+ error_libc_exit();
+
+ i->type = type;
+ i->x = x;
+ i->y = y;
+ i->vy = 0;
+ if (type == ITEM_TYPE_GOOMBA || type == ITEM_TYPE_KOOPA)
+ i->dir = -1;
+ else if (type == ITEM_TYPE_MUSHROOM)
+ i->dir = 2 * (rand() % 1) - 1;
+ else
+ i->dir = 0;
+ i->cnt = 0;
+ return i;
+}
+
+void item_free(Item i)
+{
+ if (i == NULL)
+ error_exit(ERR_NULL_PARAM);
+ free(i);
+}
+
+void item_end()
+{
+ if (item_enemies_pict != NULL)
+ screen_free_picture(item_enemies_pict);
+ if (item_upgrades_pict != NULL)
+ screen_free_picture(item_upgrades_pict);
+}
+
+double item_x(Item i)
+{
+ return i->x;
+}
+
+double item_y(Item i)
+{
+ return i->y;
+}
+
+double item_vx(Item i)
+{
+ return i->dir * ITEM_VELOCITY_X;
+}
+
+double item_vy(Item i)
+{
+ return i->vy;
+}
+
+int item_height(Item i)
+{
+ switch (i->type) {
+ case ITEM_TYPE_GOOMBA:
+ return ITEM_GOOMBA_H;
+ case ITEM_TYPE_KOOPA:
+ return i->dir == 0 ? ITEM_KOOPA_GROUND_H : ITEM_KOOPA_H;
+ default:
+ return ITEM_UPGRADE_H;
+ }
+}
+
+int item_width(Item i)
+{
+ switch (i->type) {
+ case ITEM_TYPE_GOOMBA:
+ return ITEM_GOOMBA_W;
+ case ITEM_TYPE_KOOPA:
+ return i->dir == 0 ? ITEM_KOOPA_GROUND_W : ITEM_KOOPA_W;
+ default:
+ return ITEM_UPGRADE_W;
+ }
+}
+
+int item_update(Item i)
+{
+ i->vy -= ITEM_GRAVITY;
+ i->y += i->vy;
+
+ i->x += i->dir * ITEM_VELOCITY_X;
+ i->cnt++;
+
+ if (i->type == ITEM_TYPE_KOOPA && i->dir == 0 &&
+ i->cnt >= ITEM_KOOPA_MAX_STILL) {
+ i->cnt = 0;
+ i->dir = 1;
+ }
+
+ return i->type == ITEM_TYPE_TEMPCOIN && i->cnt > ITEM_TEMPCOIN_LIFETIME;
+}
+
+void item_correct_on_block_collision(Item i, CollisionType dir)
+{
+ if (dir & COLLISION_TOP) {
+ i->vy = 0;
+ i->y = i->y - 2 * (((int)i->y) % BLOCK_SIZE);
+ }
+ if (dir & COLLISION_BOTTOM) {
+ i->vy = 0;
+ i->y = ((int)(i->y + BLOCK_SIZE) / BLOCK_SIZE) * BLOCK_SIZE;
+ }
+ if (dir & COLLISION_LEFT) {
+ i->x = (((int)(i->x + BLOCK_SIZE)) / BLOCK_SIZE) * BLOCK_SIZE;
+ if (i->dir != 0)
+ i->dir = 1;
+ }
+ if (dir & COLLISION_RIGHT) {
+ i->x = (((int)i->x) / BLOCK_SIZE) * BLOCK_SIZE;
+ if (i->dir != 0)
+ i->dir = -1;
+ }
+}
+
+int item_player_collide(Item i, Player p, CollisionType dir)
+{
+ switch (i->type) {
+ case ITEM_TYPE_GOOMBA:
+ if (dir & COLLISION_BOTTOM) {
+ return 1;
+ } else {
+ if (player_vulnerable(p))
+ player_downgrade(p);
+ return 0;
+ }
+ case ITEM_TYPE_KOOPA:
+ if (dir & COLLISION_BOTTOM && i->dir == 0) {
+ return 1;
+ } else if (dir & COLLISION_BOTTOM) {
+ i->dir = 0;
+ i->cnt = 0;
+ return 0;
+ } else {
+ if (player_vulnerable(p))
+ player_downgrade(p);
+ return 0;
+ }
+ case ITEM_TYPE_MUSHROOM:
+ player_upgrade_to(p, PLAYER_ST_BIG);
+ return 1;
+ case ITEM_TYPE_FLOWER:
+ player_upgrade_to(p, PLAYER_ST_FLOWER);
+ return 1;
+ case ITEM_TYPE_COIN:
+ player_add_coin(p);
+ return 1;
+ case ITEM_TYPE_TEMPCOIN:
+ return 0;
+ default:
+ error_exit(ERR_OUT_OF_RANGE);
+ return 0; // Execution will never reach this point.
+ }
+}
+
+
+void item_render(Screen scr, Item i, int scroll)
+{
+ Picture pict;
+ int x, y, w = item_width(i), h = item_height(i);
+
+ if (item_enemies_pict == NULL)
+ item_enemies_pict = screen_get_picture(ITEM_ENEMIES_FILE);
+ if (item_upgrades_pict == NULL)
+ item_upgrades_pict = screen_get_picture(ITEM_UPGRADES_FILE);
+
+ switch (i->type) {
+ case ITEM_TYPE_GOOMBA:
+ pict = item_enemies_pict;
+ x = ITEM_GOOMBA_X +
+ ((i->cnt / ITEM_ANIM_TICKS) % ITEM_GOOMBA_ANIM_NO)
+ * ITEM_ANIM_X_SHIFT;
+ y = ITEM_GOOMBA_Y;
+ break;
+ case ITEM_TYPE_KOOPA:
+ pict = item_enemies_pict;
+ if (i->dir == 0) {
+ x = ITEM_KOOPA_GROUND_X;
+ y = ITEM_KOOPA_GROUND_Y;
+ } else {
+ x = ITEM_KOOPA_X +
+ ((i->cnt / ITEM_ANIM_TICKS) %
+ ITEM_KOOPA_ANIM_NO)
+ * ITEM_ANIM_X_SHIFT;
+ y = ITEM_KOOPA_Y;
+ }
+ break;
+ case ITEM_TYPE_MUSHROOM:
+ pict = item_upgrades_pict;
+ x = ITEM_MUSHROOM_X;
+ y = ITEM_MUSHROOM_Y;
+ break;
+ case ITEM_TYPE_FLOWER:
+ pict = item_upgrades_pict;
+ x = ITEM_FLOWER_X +
+ ((i->cnt / ITEM_ANIM_TICKS) % ITEM_FLOWER_ANIM_NO)
+ * ITEM_ANIM_X_SHIFT;
+ y = ITEM_FLOWER_Y;
+ break;
+ case ITEM_TYPE_COIN:
+ case ITEM_TYPE_TEMPCOIN:
+ pict = item_upgrades_pict;
+ x = ITEM_COIN_X;
+ y = ITEM_COIN_Y;
+ break;
+ default:
+ error_exit(ERR_OUT_OF_RANGE);
+ return; // Execution will never reach this point
+ }
+
+ screen_place(
+ scr,
+ pict,
+ i->x - scroll,
+ screen_height(scr) - i->y - h,
+ x,
+ y,
+ w,
+ h,
+ i->dir == 1);
+}