Esempio n. 1
0
/**
 * Checks whether a collision occurs between self and other if self
 * moves from (x,y) to (new_x, new_y) in direction d.
 *
 * If other is a tile event, also indicates if the player can use it
 * as a "bridge" to step across without hitting the underlying tile
 * layer.
 */
static CollisionResult TestCollisionDuringMove(
	int x,
	int y,
	int new_x,
	int new_y,
	int d,
	const Game_Character& self,
	const Game_Event& other
) {
	if (!other.GetActive()) {
		return NoCollision;
	}

	if (&self == &other) {
		return NoCollision;
	}

	if (other.GetThrough()) {
		return NoCollision;
	}

	if (!other.IsInPosition(x, y) && !other.IsInPosition(new_x, new_y)) {
		return NoCollision;
	}

	if (&self != Main_Data::game_player.get()) {
		if (other.IsInPosition(new_x, new_y) && (self.IsOverlapForbidden() || other.IsOverlapForbidden())) {
			return Collision;
		}
	}

	if (other.IsInPosition(new_x, new_y) && self.GetLayer() == other.GetLayer()) {
		return Collision;
	}

	if (other.GetLayer() == RPG::EventPage::Layers_below) {
		int tile_id = other.GetTileId();
		if ((passages_up[tile_id] & Passable::Above) != 0) {
			return NoCollision;
		}
		if (other.IsInPosition(x,y) && (passages_up[tile_id] & DirToMask(d)) != 0) {
			return CanStepOffCurrentTile;
		}
		else if (other.IsInPosition(new_x, new_y) && (passages_up[tile_id] & DirToMask(Game_Character::ReverseDir(d))) != 0) {
			return CanStepOntoNewTile;
		} else {
			return Collision;
		}
	}

	return NoCollision;
}
Esempio n. 2
0
bool Game_Map::MakeWay(int x, int y, int d, const Game_Character& self, bool force_through) {
	int new_x = RoundX(x + (d == Game_Character::Right ? 1 : d == Game_Character::Left ? -1 : 0));
	int new_y = RoundY(y + (d == Game_Character::Down ? 1 : d == Game_Character::Up ? -1 : 0));

	if (!Game_Map::IsValid(new_x, new_y))
		return false;

	if (self.GetThrough() || force_through) return true;

	// A character can move to a position with an impassable tile by
	// standing on top of an event below it. These flags track whether
	// we stepped off an event and therefore don't need to check the
	// passability of the tile layer below.
	bool stepped_off_event = false;
	bool stepped_onto_event = false;

	for (Game_Event& other : GetEvents()) {
		CollisionResult result = TestCollisionDuringMove(x, y, new_x, new_y, d, self, other);
		if (result == Collision) {
			// Try updating the offending event to give it a chance to move out of the
			// way and recheck.
			other.UpdateParallel();
			if (TestCollisionDuringMove(x, y, new_x, new_y, d, self, other) == Collision) {
				return false;
			}
		}
		else if (result == CanStepOffCurrentTile) {
			stepped_off_event = true;
		} else if (result == CanStepOntoNewTile) {
			stepped_onto_event = true;
		}
	}

	if (vehicles[0]->IsInPosition(new_x, new_y) || vehicles[1]->IsInPosition(new_x, new_y)) {
		return false;
	}

	if (Main_Data::game_player->IsInPosition(new_x, new_y)
			&& !Main_Data::game_player->GetThrough()
			&& self.GetLayer() == RPG::EventPage::Layers_same) {
		// Update the Player to see if they'll move and recheck.
		Main_Data::game_player->Update(!first_frame);
		if (Main_Data::game_player->IsInPosition(new_x, new_y)) {
			return false;
		}
	}

	return
		(stepped_off_event || IsPassableTile(DirToMask(d), x + y * GetWidth()))
		&& (stepped_onto_event || IsPassableTile(DirToMask(Game_Character::ReverseDir(d)), new_x + new_y * GetWidth()));
}
Esempio n. 3
0
void Walk(const char*  path,POINT &pos,POINT &dir, POINT &minpt,POINT &maxpt)
{
    POINT enter_dir=dir;///enter direction for cell

    path++;
    pos+=dir;
    ///enter maze


    for(;*path;path++)
    {

        switch(*path)
        {
            case 'W':

                if(minpt.real()>pos.real())minpt.real()=pos.real();
                if(minpt.imag()>pos.imag())minpt.imag()=pos.imag();

                if(maxpt.real()<pos.real())maxpt.real()=pos.real();
                if(maxpt.imag()<pos.imag())maxpt.imag()=pos.imag();

                ///break walls in enter and exit directions
                maze[std::make_pair(pos.real(),pos.imag())]|=DirToMask(-enter_dir);
                maze[std::make_pair(pos.real(),pos.imag())]|=DirToMask(+dir);

                pos+=dir;

                enter_dir=dir;

                break;

            case 'L':
                dir*=POINT(0,1);
                break;

            case 'R':
                dir*=POINT(0,-1);
                break;
        }
    }

}
Esempio n. 4
0
bool Game_Map::IsPassable(int x, int y, int d, const Game_Character* self_event) {
	// TODO: this and MakeWay share a lot of code.
	if (!Game_Map::IsValid(x, y)) return false;

	int bit = DirToMask(d);

	int tile_id;

	if (self_event) {
		bool pass = false;
		std::vector<Game_Event*> events;
		std::vector<Game_Event*>::iterator it;

		Game_Map::GetEventsXY(events, x, y);
		for (it = events.begin(); it != events.end(); ++it) {
			if (*it == self_event || (*it)->GetThrough()) {
				continue;
			}

			if (self_event != Main_Data::game_player.get()) {
				if (self_event->IsOverlapForbidden() || (*it)->IsOverlapForbidden())
					return false;
			}

			if ((*it)->GetLayer() == self_event->GetLayer()) {
				if (self_event->IsInPosition(x, y))
					pass = true;
				else
					return false;
			}
			else if ((*it)->GetLayer() == RPG::EventPage::Layers_below) {
				// Event layer Chipset Tile
				tile_id = (*it)->GetTileId();
				if ((passages_up[tile_id] & Passable::Above) != 0)
					continue;
				if ((passages_up[tile_id] & bit) != 0)
					pass = true;
				else
					return false;
			}
		}

		if (!self_event->IsInPosition(x, y) && (vehicles[0]->IsInPosition(x, y) || vehicles[1]->IsInPosition(x, y)))
			return false;

		if (pass) // All events here are passable
			return true;
	}

	return IsPassableTile(bit, x + y * GetWidth());
}