Ejemplo n.º 1
0
void AgiEngine::motionMoveObj(VtEntry *v) {
	v->direction = getDirection(v->xPos, v->yPos, v->parm1, v->parm2, v->stepSize);

	// Update V6 if ego
	if (isEgoView(v))
		_game.vars[vEgoDir] = v->direction;

	if (v->direction == 0)
		inDestination(v);
}
Ejemplo n.º 2
0
/**
 * Update position of objects
 * This function updates the position of all animated, updating view
 * table entries according to its motion type, step size, etc. The
 * new position must be valid according to the sprite positioning
 * rules, otherwise the previous position will be kept.
 */
void AgiEngine::updatePosition() {
	VtEntry *v;
	int x, y, oldX, oldY, border;

	_game.vars[vBorderCode] = 0;
	_game.vars[vBorderTouchEgo] = 0;
	_game.vars[vBorderTouchObj] = 0;

	for (v = _game.viewTable; v < &_game.viewTable[MAX_VIEWTABLE]; v++) {
		if ((v->flags & (ANIMATED | UPDATE | DRAWN)) != (ANIMATED | UPDATE | DRAWN)) {
			continue;
		}

		if (v->stepTimeCount != 0) {
			if (--v->stepTimeCount != 0)
				continue;
		}

		v->stepTimeCount = v->stepTime;

		x = oldX = v->xPos;
		y = oldY = v->yPos;

		// If object has moved, update its position
		if (~v->flags & UPDATE_POS) {
			int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 };
			int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 };
			x += v->stepSize * dx[v->direction];
			y += v->stepSize * dy[v->direction];
		}

		// Now check if it touched the borders
		border = 0;

		// Check left/right borders
		if (x < 0) {
			x = 0;
			border = 4;
		} else if (x <= 0 && getVersion() == 0x3086) {	// KQ4
			x = 0;	// See Sarien bug #590462
			border = 4;
		} else if (v->entry == 0 && x == 0 && v->flags & ADJ_EGO_XY) {
			// Extra test to walk west clicking the mouse
			x = 0;
			border = 4;
		} else if (x + v->xSize > _WIDTH) {
			x = _WIDTH - v->xSize;
			border = 2;
		}

		// Check top/bottom borders.
		if (y - v->ySize + 1 < 0) {
			y = v->ySize - 1;
			border = 1;
		} else if (y > _HEIGHT - 1) {
			y = _HEIGHT - 1;
			border = 3;
		} else if ((~v->flags & IGNORE_HORIZON) && y <= _game.horizon) {
			debugC(4, kDebugLevelSprites, "y = %d, horizon = %d", y, _game.horizon);
			y = _game.horizon + 1;
			border = 1;
		}

		// Test new position. rollback if test fails
		v->xPos = x;
		v->yPos = y;
		if (checkCollision(v) || !checkPriority(v)) {
			v->xPos = oldX;
			v->yPos = oldY;
			border = 0;
			fixPosition(v->entry);
		}

		if (border != 0) {
			if (isEgoView(v)) {
				_game.vars[vBorderTouchEgo] = border;
			} else {
				_game.vars[vBorderCode] = v->entry;
				_game.vars[vBorderTouchObj] = border;
			}
			if (v->motion == MOTION_MOVE_OBJ) {
				inDestination(v);
			}
		}

		v->flags &= ~UPDATE_POS;
	}
}
Ejemplo n.º 3
0
// If main_cycle returns false, don't process more events!
int AgiEngine::mainCycle() {
	unsigned int key, kascii;
	VtEntry *v = &_game.viewTable[0];

	pollTimer();
	updateTimer();

	key = doPollKeyboard();

	// In AGI Mouse emulation mode we must update the mouse-related
	// vars in every interpreter cycle.
	//
	// We run AGIMOUSE always as a side effect
	if (getFeatures() & GF_AGIMOUSE || true) {
		_game.vars[28] = _mouse.x / 2;
		_game.vars[29] = _mouse.y;
	}
	if (key == KEY_PRIORITY) {
		_sprites->eraseBoth();
		_debug.priority = !_debug.priority;
		_picture->showPic();
		_sprites->blitBoth();
		_sprites->commitBoth();
		key = 0;
	}

	if (key == KEY_STATUSLN) {
		_debug.statusline = !_debug.statusline;
		writeStatus();
		key = 0;
	}

	// Click-to-walk mouse interface
	if (_game.playerControl && v->flags & ADJ_EGO_XY) {
		int toX = v->parm1;
		int toY = v->parm2;

		// AGI Mouse games use ego's sprite's bottom left corner for mouse walking target.
		// Amiga games use ego's sprite's bottom center for mouse walking target.
		// TODO: Check what Atari ST AGI and Apple IIGS AGI use for mouse walking target.
		if (getPlatform() == Common::kPlatformAmiga)
			toX -= (v->xSize / 2); // Center ego's sprite horizontally

		// Adjust ego's sprite's mouse walking target position (These parameters are
		// controlled with the adj.ego.move.to.x.y-command). Note that these values rely
		// on the horizontal centering of the ego's sprite at least on the Amiga platform.
		toX += _game.adjMouseX;
		toY += _game.adjMouseY;

		v->direction = getDirection(v->xPos, v->yPos, toX, toY, v->stepSize);

		if (v->direction == 0)
			inDestination(v);
	}

	kascii = KEY_ASCII(key);

	if (kascii)
		setvar(vKey, kascii);

process_key:

	switch (_game.inputMode) {
	case INPUT_NORMAL:
		if (!handleController(key)) {
			if (key == 0 || !_game.inputEnabled)
				break;
			handleKeys(key);

			// if ESC pressed, activate menu before
			// accept.input from the interpreter cycle
			// sets the input mode to normal again
			// (closes: #540856)
			if (key == KEY_ESCAPE) {
				key = 0;
				goto process_key;
			}

			// commented out to close Sarien bug #438872
			//if (key)
			//	_game.keypress = key;
		}
		break;
	case INPUT_GETSTRING:
		handleController(key);
		handleGetstring(key);
		setvar(vKey, 0);	// clear ENTER key
		break;
	case INPUT_MENU:
		_menu->keyhandler(key);
		_gfx->doUpdate();
		return false;
	case INPUT_NONE:
		handleController(key);
		if (key)
			_game.keypress = key;
		break;
	}
	_gfx->doUpdate();

	if (_game.msgBoxTicks > 0)
		_game.msgBoxTicks--;

	return true;
}
Ejemplo n.º 4
0
// We return the current key, or 0 if no key was pressed
uint16 AgiEngine::processAGIEvents() {
	uint16 key;
	ScreenObjEntry *screenObjEgo = &_game.screenObjTable[SCREENOBJECTS_EGO_ENTRY];

	wait(10);
	key = doPollKeyboard();

	// In AGI Mouse emulation mode we must update the mouse-related
	// vars in every interpreter cycle.
	//
	// We run AGIMOUSE always as a side effect
	setVar(VM_VAR_MOUSE_X, _mouse.pos.x / 2);
	setVar(VM_VAR_MOUSE_Y, _mouse.pos.y);

	if (!cycleInnerLoopIsActive()) {
		// Click-to-walk mouse interface
		if (_game.playerControl && (screenObjEgo->flags & fAdjEgoXY)) {
			int toX = screenObjEgo->move_x;
			int toY = screenObjEgo->move_y;

			// AGI Mouse games use ego's sprite's bottom left corner for mouse walking target.
			// Amiga games use ego's sprite's bottom center for mouse walking target.
			// Atari ST and Apple II GS seem to use the bottom left
			if (getPlatform() == Common::kPlatformAmiga)
				toX -= (screenObjEgo->xSize / 2); // Center ego's sprite horizontally

			// Adjust ego's sprite's mouse walking target position (These parameters are
			// controlled with the adj.ego.move.to.x.y-command). Note that these values rely
			// on the horizontal centering of the ego's sprite at least on the Amiga platform.
			toX += _game.adjMouseX;
			toY += _game.adjMouseY;

			screenObjEgo->direction = getDirection(screenObjEgo->xPos, screenObjEgo->yPos, toX, toY, screenObjEgo->stepSize);

			if (screenObjEgo->direction == 0)
				inDestination(screenObjEgo);
		}
	}

	handleMouseClicks(key);

	if (!cycleInnerLoopIsActive()) {
		// no inner loop active at the moment, regular processing

		if (key) {
			if (!handleController(key)) {
				if (key) {
					// Only set VAR_KEY, when no controller/direction was detected
					setVar(VM_VAR_KEY, key & 0xFF);
					if (_text->promptIsEnabled()) {
						_text->promptKeyPress(key);
					}
				}
			}
		}

		if (_menu->delayedExecuteActive()) {
			_menu->execute();
		}

	} else {
		// inner loop active
		// call specific workers
		switch (_game.cycleInnerLoopType) {
		case CYCLE_INNERLOOP_GETSTRING: // loop called from TextMgr::stringEdit()
		case CYCLE_INNERLOOP_GETNUMBER:
			if (key) {
				_text->stringKeyPress(key);
			}
			break;

		case CYCLE_INNERLOOP_INVENTORY: // loop called from InventoryMgr::show()
			if (key) {
				_inventory->keyPress(key);
			}
			break;

		case CYCLE_INNERLOOP_MENU_VIA_KEYBOARD:
			if (key) {
				_menu->keyPress(key);
			}
			break;

		case CYCLE_INNERLOOP_MENU_VIA_MOUSE:
			_menu->mouseEvent(key);
			break;

		case CYCLE_INNERLOOP_SYSTEMUI_SELECTSAVEDGAMESLOT:
			if (key) {
				_systemUI->savedGameSlot_KeyPress(key);
			}
			break;

		case CYCLE_INNERLOOP_SYSTEMUI_VERIFICATION:
			_systemUI->askForVerificationKeyPress(key);
			break;

		case CYCLE_INNERLOOP_MESSAGEBOX:
			if (key) {
				_text->messageBox_KeyPress(key);
			}
			break;

		default:
			break;
		}
	}

	_gfx->updateScreen();

	return key;
}