void drawCursor() { Entity *e; if (cursor.type == TILES) { drawImage(tileImage(cursor.tileID), cursor.x, cursor.y, FALSE, 255); drawImage(tileImage(BLANK_TILE), cursor.x, cursor.y, FALSE, 255); } else { e = isSpaceEmpty(&cursor.entity); if (isValidOnMap(&cursor.entity) == 0 || e != NULL) { drawBox(game.screen, cursor.x, cursor.y, cursor.entity.w, cursor.entity.h, 255, 0, 0); } if (e != NULL) { setStatusPanelMessage("%s : %d %d", (strlen(e->objectiveName) == 0 ? e->name : e->objectiveName), (int)e->x, (int)e->y); } else { setStatusPanelMessage(""); } cursor.entity.x = getMapStartX() + cursor.x; cursor.entity.y = getMapStartY() + cursor.y; self = &cursor.entity; self->draw(); } }
void checkToMap(Entity *e) { int i, x1, x2, y1, y2, previousEnvironment; int topLeft, topRight, bottomLeft, bottomRight, previousY2, previous; int tempX, tempY, wasOnGround; wasOnGround = (e->flags & ON_GROUND); /* Remove the entity from the ground */ e->flags &= ~ON_GROUND; /* Set environment to air */ previousEnvironment = e->environment; e->environment = AIR; /* Test the horizontal movement first */ i = e->h > TILE_SIZE ? TILE_SIZE : e->h; for (;;) { x1 = (e->x + e->dirX) / TILE_SIZE; x2 = (e->x + e->dirX + e->w - 1) / TILE_SIZE; y1 = (e->y) / TILE_SIZE; y2 = (e->y + i - 1) / TILE_SIZE; if (x1 >= 0 && x2 < MAX_MAP_X && y1 >= 0 && y2 < MAX_MAP_Y) { topLeft = mapTileAt(x1, y1); topRight = mapTileAt(x2, y1); bottomLeft = mapTileAt(x1, y2); bottomRight = mapTileAt(x2, y2); if (e->dirX > 0) { /* Trying to move right */ previous = (e->x + e->w - 1) / TILE_SIZE; previous = mapTileAt(previous, y2); if (previous >= SLOPE_UP_START && previous <= SLOPE_UP_END) { if (i == e->h) { if (bottomRight >= SLOPE_UP_START && bottomRight <= SLOPE_UP_END) { e->y -= e->dirX; e->dirY = 0; e->flags |= ON_GROUND; } else if (bottomRight != BLANK_TILE && bottomRight < BACKGROUND_TILE_START) { e->y = (int)((e->y + e->h - 1) / TILE_SIZE); e->y *= TILE_SIZE; e->y -= e->h + 0.5; e->dirY = 0; e->flags |= ON_GROUND; previous = mapTileAt(x2, (e->y + e->h - 1) / TILE_SIZE); if (previous >= SLOPE_UP_START && previous <= SLOPE_UP_END) { e->y -= e->dirX; e->dirY = 0; e->flags |= ON_GROUND; } } } } else if (bottomRight >= SLOPE_UP_START && bottomRight <= SLOPE_UP_END) { if (i == e->h) { if (!(e->flags & FLY)) { if ((e->flags & BOUNCES) && e->dirY > 4) { e->dirY = -e->dirY * 2 / 3; } else { e->dirY = 0; e->flags |= ON_GROUND; } } else { e->x = x2 * TILE_SIZE; e->x -= e->w; e->dirX = 0; } if (e->type == PROJECTILE) { e->die(); return; } } } else if ((previous >= SLOPE_UP_START && previous <= SLOPE_UP_END) && !(bottomRight >= SLOPE_UP_START && bottomRight <= SLOPE_UP_END)) { } else if (bottomLeft >= SLOPE_DOWN_START && bottomLeft <= SLOPE_DOWN_END) { e->flags |= ON_GROUND; } else if ((topRight >= JUMP_THROUGH_TILE_START && topRight <= JUMP_THROUGH_TILE_END) || ((bottomRight >= JUMP_THROUGH_TILE_START && bottomRight <= JUMP_THROUGH_TILE_END))) { } else if ((topRight != BLANK_TILE && topRight < BACKGROUND_TILE_START) || (bottomRight != BLANK_TILE && bottomRight < BACKGROUND_TILE_START)) { /* Place the player as close to the solid tile as possible */ e->x = x2 * TILE_SIZE; e->x -= e->w; e->dirX = (e->flags & BOUNCES) ? -e->dirX : 0; if ((e->flags & GRABBING) && e->target != NULL) { e->target->dirX = 0; } if (e->type == PROJECTILE) { e->die(); return; } } } else if (e->dirX < 0) { /* Trying to move left */ previous = (e->x) / TILE_SIZE; previous = mapTileAt(previous, y2); if (previous >= SLOPE_DOWN_START && previous <= SLOPE_DOWN_END) { if (i == e->h) { if (bottomLeft >= SLOPE_DOWN_START && bottomLeft <= SLOPE_DOWN_END) { e->y += e->dirX; e->dirY = 0; e->flags |= ON_GROUND; } else if (bottomLeft != BLANK_TILE && bottomLeft < BACKGROUND_TILE_START) { e->y = (int)((e->y + e->h - 1) / TILE_SIZE); e->y *= TILE_SIZE; e->y -= e->h + 0.5; e->dirY = 0; e->flags |= ON_GROUND; previous = mapTileAt(x1, (e->y + e->h - 1) / TILE_SIZE); if (previous >= SLOPE_DOWN_START && previous <= SLOPE_DOWN_END) { e->y += e->dirX; e->dirY = 0; e->flags |= ON_GROUND; } } } } else if (bottomLeft >= SLOPE_DOWN_START && bottomLeft <= SLOPE_DOWN_END) { if (i == e->h) { if (!(e->flags & FLY)) { if ((e->flags & BOUNCES) && e->dirY > 4) { e->dirY = -e->dirY * 2 / 3; } else { e->dirY = 0; e->flags |= ON_GROUND; } } else { e->x = (x1 + 1) * TILE_SIZE; e->dirX = 0; } if (e->type == PROJECTILE) { e->die(); return; } } } else if ((previous >= SLOPE_DOWN_START && previous <= SLOPE_DOWN_END) && !(bottomLeft >= SLOPE_DOWN_START && bottomLeft <= SLOPE_DOWN_END)) { } else if (bottomRight >= SLOPE_UP_START && bottomRight <= SLOPE_UP_END) { e->flags |= ON_GROUND; } else if ((topLeft >= JUMP_THROUGH_TILE_START && topLeft <= JUMP_THROUGH_TILE_END) || ((bottomLeft >= JUMP_THROUGH_TILE_START && bottomLeft <= JUMP_THROUGH_TILE_END))) { } else if ((topLeft != BLANK_TILE && topLeft < BACKGROUND_TILE_START) || (bottomLeft != BLANK_TILE && bottomLeft < BACKGROUND_TILE_START)) { /* Place the player as close to the solid tile as possible */ e->x = (x1 + 1) * TILE_SIZE; e->dirX = (e->flags & BOUNCES) ? -e->dirX : 0; if ((e->flags & GRABBING) && e->target != NULL) { e->target->dirX = 0; } if (e->type == PROJECTILE) { e->die(); return; } } } } /* Exit this loop if we have tested all of the body */ if (i == e->h || e->h <= TILE_SIZE) { break; } /* Test the next block */ i += TILE_SIZE; if (i > e->h) { i = e->h; } } /* Now test the vertical movement */ i = e->w > TILE_SIZE ? TILE_SIZE : e->w; for (;;) { x1 = (e->x) / TILE_SIZE; x2 = (e->x + i - 1) / TILE_SIZE; y1 = (e->y + e->dirY) / TILE_SIZE; y2 = (e->y + e->dirY + e->h - 1) / TILE_SIZE; if (x1 >= 0 && x2 < MAX_MAP_X && y1 >= 0 && y2 < MAX_MAP_Y) { topLeft = mapTileAt(x1, y1); topRight = mapTileAt(x2, y1); bottomLeft = mapTileAt(x1, y2); bottomRight = mapTileAt(x2, y2); if (e->dirY > 0) { /* Trying to move down */ if (bottomRight >= SLOPE_UP_START && bottomRight <= SLOPE_UP_END) { if (i == e->w) { tempX = (int)(e->x + i - 1) % TILE_SIZE; tempY = (int)(e->y + e->dirY + e->h - 1) % TILE_SIZE; tempX = TILE_SIZE - tempX; if (tempY > tempX || wasOnGround != 0) { e->y = y2 * TILE_SIZE; e->y -= e->h; e->y += tempX + 1; if ((e->flags & BOUNCES) && e->dirY > 4) { e->dirY = -e->dirY * 2 / 3; } else { e->dirY = 0; e->flags |= ON_GROUND; } } } if (e->type == PROJECTILE) { e->die(); return; } } else if (bottomLeft >= SLOPE_DOWN_START && bottomLeft <= SLOPE_DOWN_END) { if (i == (e->w > TILE_SIZE ? TILE_SIZE : e->w)) { tempX = (int)(e->x) % TILE_SIZE; tempY = (int)(e->y + e->dirY + e->h - 1) % TILE_SIZE; if (tempY > tempX || wasOnGround != 0) { e->y = y2 * TILE_SIZE; e->y -= e->h; e->y += tempX + 1; if ((e->flags & BOUNCES) && e->dirY > 4) { e->dirY = -e->dirY * 2 / 3; } else { e->dirY = 0; e->flags |= ON_GROUND; } } } if (e->type == PROJECTILE) { e->die(); return; } } else if ((bottomLeft >= JUMP_THROUGH_TILE_START && bottomLeft <= JUMP_THROUGH_TILE_END) || ((bottomRight >= JUMP_THROUGH_TILE_START && bottomRight <= JUMP_THROUGH_TILE_END))) { previousY2 = y2; x1 = (e->x) / TILE_SIZE; x2 = (e->x + i - 1) / TILE_SIZE; y2 = (e->y + e->h - 1) / TILE_SIZE; bottomLeft = mapTileAt(x1, y2); bottomRight = mapTileAt(x2, y2); if (!((bottomLeft >= JUMP_THROUGH_TILE_START && bottomLeft <= JUMP_THROUGH_TILE_END) || ((bottomRight >= JUMP_THROUGH_TILE_START && bottomRight <= JUMP_THROUGH_TILE_END)))) { y2 = previousY2; /* Place the player as close to the solid tile as possible */ e->y = y2 * TILE_SIZE; e->y -= e->h; if ((e->flags & BOUNCES) && e->dirY > 4) { e->dirY = -e->dirY * 2 / 3; } else { e->dirY = 0; e->flags |= ON_GROUND; } } if (e->type == PROJECTILE) { e->die(); return; } } else if ((bottomLeft != BLANK_TILE && bottomLeft < BACKGROUND_TILE_START) || (bottomRight != BLANK_TILE && bottomRight < BACKGROUND_TILE_START)) { /* Place the player as close to the solid tile as possible */ e->y = y2 * TILE_SIZE; e->y -= e->h; if ((e->flags & BOUNCES) && e->dirY > 4) { e->dirY = -e->dirY * 2 / 3; } else { e->dirY = 0; e->flags |= ON_GROUND; } if (e->type == PROJECTILE) { e->die(); return; } } } else if (e->dirY < 0) { /* Trying to move up */ if ((topLeft >= JUMP_THROUGH_TILE_START && topLeft <= JUMP_THROUGH_TILE_END) || ((topRight >= JUMP_THROUGH_TILE_START && topRight <= JUMP_THROUGH_TILE_END))) { } else if ((topLeft != BLANK_TILE && topLeft < BACKGROUND_TILE_START) || (topRight != BLANK_TILE && topRight < BACKGROUND_TILE_START)) { /* Place the player as close to the solid tile as possible */ e->y = (y1 + 1) * TILE_SIZE; e->dirY = (e->flags & BOUNCES) ? -e->dirY : 0; if (e->type == PROJECTILE) { e->die(); return; } } } } if (i == e->w || e->w <= TILE_SIZE) { break; } i += TILE_SIZE; if (i > e->w) { i = e->w; } } /* Now apply the movement */ e->x += e->dirX; e->y += e->dirY; x1 = (e->type == PLAYER || (e->flags & LIMIT_TO_SCREEN)) ? getPlayerMinX() : getMapMinX(); x2 = (e->type == PLAYER || (e->flags & LIMIT_TO_SCREEN)) ? getPlayerMaxX() : getMapMaxX(); y1 = (e->flags & LIMIT_TO_SCREEN) ? getMapStartY() : getMapMinY() - 300; if (e->x < x1) { e->x = x1; e->dirX = 0; if ((e->flags & GRABBING) && e->target != NULL) { e->target->dirX = 0; } if (e->type == PROJECTILE) { e->die(); } } else if (e->x + e->w >= x2) { e->x = x2 - e->w - 1; e->dirX = 0; if ((e->flags & GRABBING) && e->target != NULL) { e->target->dirX = 0; } if (e->type == PROJECTILE) { e->die(); } } if (e->y > getMapMaxY() && e->y - e->dirY <= getMapMaxY()) { e->flags &= ~(HELPLESS|INVULNERABLE); if (e->fallout == NULL) { printf("%s has no fallout defined. Removing\n", e->name); e->inUse = FALSE; return; } else { e->fallout(); } } else if (e->y < y1) { /* Way too high... */ e->y = y1; e->dirY = 0; } x1 = (e->x) / TILE_SIZE; x2 = (e->x + e->w - 1) / TILE_SIZE; y1 = (e->y) / TILE_SIZE; y2 = (e->y + e->h - 1) / TILE_SIZE; topLeft = mapTileAt(x1, y1); topRight = mapTileAt(x2, y1); bottomLeft = mapTileAt(x1, y2); bottomRight = mapTileAt(x2, y2); if ((topLeft >= LAVA_TILE_START && topLeft <= LAVA_TILE_END) || (bottomLeft >= LAVA_TILE_START && bottomLeft <= LAVA_TILE_END) || (topRight >= LAVA_TILE_START && topRight <= LAVA_TILE_END) || (bottomRight >= LAVA_TILE_START && bottomRight <= LAVA_TILE_END)) { e->environment = LAVA; if (previousEnvironment != LAVA && e->fallout != NULL) { /* Fire based entities won't die */ if (e->element != FIRE) { if (e->type != TEMP_ITEM) { playSoundToMap("sound/common/lava", -1, e->x, e->y, 0); } e->flags &= ~(HELPLESS|INVULNERABLE); e->fallout(); } } } else if ((topLeft >= SLIME_TILE_START && topLeft <= SLIME_TILE_BLEND) || (bottomLeft >= SLIME_TILE_START && bottomLeft <= SLIME_TILE_BLEND) || (topRight >= SLIME_TILE_START && topRight <= SLIME_TILE_BLEND) || (bottomRight >= SLIME_TILE_START && bottomRight <= SLIME_TILE_BLEND)) { e->environment = SLIME; if (previousEnvironment != SLIME && e->fallout != NULL) { /* Slime based entities won't die */ if (e->element != SLIME) { if (e->type != TEMP_ITEM) { playSoundToMap("sound/common/slime", -1, e->x, e->y, 0); } e->flags &= ~(HELPLESS|INVULNERABLE); e->fallout(); } } } else { y2 = (e->y + (e->h / 2)) / TILE_SIZE; bottomLeft = mapTileAt(x1, y2); bottomRight = mapTileAt(x2, y2); if ((topLeft >= WATER_TILE_START && topLeft <= WATER_TILE_END) && (bottomLeft >= WATER_TILE_START && bottomLeft <= WATER_TILE_END) && (topRight >= WATER_TILE_START && topRight <= WATER_TILE_END) && (bottomRight >= WATER_TILE_START && bottomRight <= WATER_TILE_END)) { e->environment = WATER; if (previousEnvironment != WATER && e->fallout != NULL) { if (e->type != TEMP_ITEM) { playSoundToMap("sound/common/splash", -1, e->x, e->y, 0); } if (!(e->flags & FLOATS)) { e->flags &= ~(HELPLESS|INVULNERABLE); e->fallout(); } } } } }
void doCursor() { char name[MAX_VALUE_LENGTH]; int x, y; cursor.x = input.mouseX; cursor.y = input.mouseY; if (cursor.type == TILES || cursor.snapToGrid == 1) { cursor.x /= TILE_SIZE; cursor.y /= TILE_SIZE; cursor.x *= TILE_SIZE; cursor.y *= TILE_SIZE; } if (cursor.y >= SCREEN_HEIGHT - TILE_SIZE) { cursor.y = SCREEN_HEIGHT - TILE_SIZE * 2; } if (input.left == 1) { mapStartXNext(-TILE_SIZE); } else if (input.right == 1) { mapStartXNext(TILE_SIZE); } if (input.up == 1) { mapStartYNext(-TILE_SIZE); } else if (input.down == 1) { mapStartYNext(TILE_SIZE); } if (input.snap == 1) { cursor.snapToGrid = 1 - cursor.snapToGrid; input.snap = 0; } if (input.activate == 1) { cursor.entity.face = (cursor.entity.face == RIGHT ? LEFT : RIGHT); input.activate = 0; } if (input.block == 1) { if (cursor.type == TILES) { x = (getMapStartX() + cursor.x) / TILE_SIZE; y = (getMapStartY() + cursor.y) / TILE_SIZE; while (mapTileAt(x, y) == BLANK_TILE && x >= 0) { setTileAt(x, y, cursor.tileID); x--; } x = (getMapStartX() + cursor.x) / TILE_SIZE; x++; while (mapTileAt(x, y) == BLANK_TILE && x < MAX_MAP_X) { setTileAt(x, y, cursor.tileID); x++; } } } if (input.add == 1) { if (cursor.type == TILES) { setTileAt((getMapStartX() + cursor.x) / TILE_SIZE, (getMapStartY() + cursor.y) / TILE_SIZE, cursor.tileID); } else { /* Entities can only be placed in blank spaces */ if (isValidOnMap(&cursor.entity) == 1 && isSpaceEmpty(&cursor.entity) == NULL) { if (cursor.entityType == 0) { setPlayerLocation(getMapStartX() + cursor.x, getMapStartY() + cursor.y); } else { if (strcmpignorecase(cursor.entity.name, "lift/lift_target") == 0) { snprintf(name, sizeof(name), "NEW_TARGET_%03d", targetID); addTarget(getMapStartX() + cursor.x, getMapStartY() + cursor.y, name); targetID++; } else { cursor.entity.startX = getMapStartX() + cursor.x; cursor.entity.startY = getMapStartY() + cursor.y; cursor.entity.endX = getMapStartX() + cursor.x; cursor.entity.endY = getMapStartY() + cursor.y; addEntity(cursor.entity, getMapStartX() + cursor.x, getMapStartY() + cursor.y); } } } input.add = 0; } } else if (input.remove == 1) { if (cursor.type == TILES) { setTileAt((getMapStartX() + cursor.x) / TILE_SIZE, (getMapStartY() + cursor.y) / TILE_SIZE, BLANK_TILE); } else { self = isSpaceEmpty(&cursor.entity); if (self != NULL) { self->inUse = FALSE; } } } if (input.cut == 1) { if (cursor.type != TILES) { self = isSpaceEmpty(&cursor.entity); if (self != NULL) { cursor.entity = *self; self->inUse = FALSE; } } input.cut = 0; } if (input.previous == 1) { if (cursor.type == TILES) { cursor.tileID = prevTile(cursor.tileID); } else { cursor.entityType--; if (cursor.entityType < 0) { cursor.entityType = entityNamesLength - 1; } memset(&cursor.entity, 0, sizeof(Entity)); cursor.entity.draw = &drawLoopingAnimationToMap; cursor.entity.weight = 0; cursor.entity.originalWeight = 0; cursor.entity.inUse = TRUE; loadProperties(entityNames[cursor.entityType], &cursor.entity); cursor.entity.active = TRUE; cursor.entity.alpha = 255; if (cursor.entity.weight == 0) { cursor.entity.weight = 1; cursor.entity.originalWeight = 1; } } input.previous = 0; } else if (input.next == 1) { if (cursor.type == TILES) { cursor.tileID = nextTile(cursor.tileID); } else { cursor.entityType++; if (cursor.entityType >= entityNamesLength) { cursor.entityType = 0; } memset(&cursor.entity, 0, sizeof(Entity)); cursor.entity.draw = &drawLoopingAnimationToMap; cursor.entity.weight = 0; cursor.entity.originalWeight = 1; cursor.entity.inUse = TRUE; loadProperties(entityNames[cursor.entityType], &cursor.entity); cursor.entity.active = TRUE; cursor.entity.alpha = 255; if (cursor.entity.weight == 0) { cursor.entity.weight = 1; cursor.entity.originalWeight = 1; } } input.next = 0; } if (input.save == 1) { if (saveMap() == TRUE) { setStatusPanelMessage("Saved"); } else { setStatusPanelMessage("Saving Failed"); } input.save = 0; } /* if (input.load == 1) { loadMap(map.filename); printf("Loaded\n"); input.load = 0; } */ if (input.left == 1 || input.right == 1 || input.up == 1 || input.down == 1) { SDL_Delay(30); } if (input.toggle == 1) { if (cursor.type == TILES) { cursor.type = ENTITIES; } else { cursor.type = TILES; } input.toggle = 0; } centerMapOnEntity(NULL); }
static void incinerate() { int x, startX, startY; Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { e = getFreeEntity(); if (e == NULL) { showErrorAndExit("No free slots to add Fire"); } loadProperties("enemy/fire", e); setEntityAnimation(e, "DOWN"); if (self->face == LEFT) { e->x = self->x + self->w - self->offsetX; } else { e->x = self->x + self->offsetX; } e->y = self->y + self->offsetY; e->x -= e->w / 2; e->action = &fireFall; e->draw = &drawLoopingAnimationToMap; e->touch = &entityTouch; e->face = self->face; e->type = ENEMY; e->health = 0; self->mental++; if (self->mental == 60) { startX = getMapStartX(); startY = getMapStartY() + SCREEN_HEIGHT - TILE_SIZE; x = 0; while (x < SCREEN_WIDTH) { e = getFreeEntity(); if (e == NULL) { showErrorAndExit("No free slots to add the Fire"); } loadProperties("boss/phoenix_die_fire", e); setEntityAnimation(e, "STAND"); e->x = startX + x; e->y = startY - e->h; e->action = &fireWait; e->touch = &entityTouch; e->draw = &drawLoopingAnimationToMap; e->type = ENEMY; e->flags |= FLY; e->layer = FOREGROUND_LAYER; e->thinkTime = 30; e->damage = 1; e->health = 0; e->maxHealth = 5; e->mental = 1; e->head = self; x += e->w; self->endY++; } } else if (self->mental > 100) { self->thinkTime = 60; self->action = &incinerateWait; } else { self->thinkTime = 3; } } checkToMap(self); }