World Limit Issues
by Theo Brinkman · in Torque Game Builder · 06/08/2006 (8:20 pm) · 4 replies
I'm trying to use the Basic Tutorial as a reference to learn the basics of TGE scripting, but I'm running into issues with my movement code. My difficulties come in to play because I need to only allow the player to move in 1/2-tile increments. I got the code working the way I want it to, and went to the next step of adding world limits so I can't go off the screen. Unfortunately, when I hit the world limits, I seem to get 'stuck'.
A basic over view of the movement code is that I set a flag to not change direction, and use moveTo() to go to the next 1/2-tile increment. When the moveTo callback happens, I clear the flag and call updateMovement() again to move if the key is still pressed. When the target position for moveTo() is the same as the current position, the callback never fires, so I check that and clear the flag if the player isn't going to move.
My initial theory with the world limits was just to clear the flag when the the world-limits collision callback was triggered, but it seems like if you are already touching the world limits and you try to move past them, that callback never happens, much like the situation with a moveTo the current position.
I figure I'm going to run into a similar situation when I start worrying about collisions with the contents of a tile map. (I'm having issues at the moment trying to wrap my brain around the tile map editor and/or getting a tile map into a level at the same scale as the player.)
Movement code is below, any suggestions on how to properly handle collisions of various sorts would be greatly appreciated. Also, is it possible to call a member function of the class in the moveMap.bindCmd?
(ie: moveMap.bindCmd(keyboard, "w", "%this.moveUp();", "%this.moveUpStop();");)
I've tried the obvious route, but just get a crash when the keypress attempts to call the keydown event function.
A basic over view of the movement code is that I set a flag to not change direction, and use moveTo() to go to the next 1/2-tile increment. When the moveTo callback happens, I clear the flag and call updateMovement() again to move if the key is still pressed. When the target position for moveTo() is the same as the current position, the callback never fires, so I check that and clear the flag if the player isn't going to move.
My initial theory with the world limits was just to clear the flag when the the world-limits collision callback was triggered, but it seems like if you are already touching the world limits and you try to move past them, that callback never happens, much like the situation with a moveTo the current position.
I figure I'm going to run into a similar situation when I start worrying about collisions with the contents of a tile map. (I'm having issues at the moment trying to wrap my brain around the tile map editor and/or getting a tile map into a level at the same scale as the player.)
Movement code is below, any suggestions on how to properly handle collisions of various sorts would be greatly appreciated. Also, is it possible to call a member function of the class in the moveMap.bindCmd?
(ie: moveMap.bindCmd(keyboard, "w", "%this.moveUp();", "%this.moveUpStop();");)
I've tried the obvious route, but just get a crash when the keypress attempts to call the keydown event function.
About the author
#2
The biggest issue right now is that even though I've set the world limits on the box, I can push it half-way past the limits (and at the same time, walk halfway into the box). I have a feeling that my problem is in the cPlayer::onCollision(...) code, which is currently just spitting out debug info, but I haven't had a chance to dig into it too deeply.
Essentially, the only ability of the player object in this game is to be able to push a single block at a time. If the player is pushing the block upward, and the block hits something (world limits or another object) the block should stop moving, and the player should not be able to move any further upward either.
06/19/2006 (8:23 pm)
Ok, I've gotten the World Limits issue resolved, and working and I'm starting to have issues with object collision to push a box around.The biggest issue right now is that even though I've set the world limits on the box, I can push it half-way past the limits (and at the same time, walk halfway into the box). I have a feeling that my problem is in the cPlayer::onCollision(...) code, which is currently just spitting out debug info, but I haven't had a chance to dig into it too deeply.
Essentially, the only ability of the player object in this game is to be able to push a single block at a time. If the player is pushing the block upward, and the block hits something (world limits or another object) the block should stop moving, and the player should not be able to move any further upward either.
#3
To check the worldLimits manually, you'll either have to use getWorldLimits() on some object (making sure that it's defined for that object of course), or do that early on in the game and store it in a global, or something like that.
-Vern
06/19/2006 (9:23 pm)
If I were you, I'd go about it "manually" rather than relying on the built-in WorldLimits feature. That is, when the player goes to push a box, it first calls a method canBoxMove(%direction) which returns true or false as to whether the box can move in that direction. This method checks for other boxes AND checks to see if the box will end up outside worldLimits if it's pushed. To check the worldLimits manually, you'll either have to use getWorldLimits() on some object (making sure that it's defined for that object of course), or do that early on in the game and store it in a global, or something like that.
-Vern
#4
That'll really take figuring out the tile editor though, and I just can't seem to wrap my brain around it yet. (I can create something that looks like it should, but it comes in tiny, and I can't figure out how to resize it, or why it's so small.)
06/20/2006 (6:24 pm)
I suspected as much. I'll probably drop the world-limits all together, since I can just put immovable objects all the way around the border of the level, and only have to worry about object-object collisions instead.That'll really take figuring out the tile editor though, and I just can't seem to wrap my brain around it yet. (I can create something that looks like it should, but it comes in tiny, and I can't figure out how to resize it, or why it's so small.)
Torque Owner Theo Brinkman
function cPlayer::onLevelLoaded(%this, %scenegraph) { // echo("cPlayer::onLevelLoaded(%this, %scenegraph);"); $player = %this; moveMap.bindCmd(keyboard, "w", "playerUp();", "playerUpStop();"); moveMap.bindCmd(keyboard, "s", "playerDown();", "playerDownStop();"); moveMap.bindCmd(keyboard, "a", "playerLeft();", "playerLeftStop();"); moveMap.bindCmd(keyboard, "d", "playerRight();", "playerRightStop();"); %this.gridSize = 2; %this.ready = true; } function cPlayer::onCollision(%srcObject, %dstObject, %srcRef, %dstRef, %time, %normal, %contacts, %points) { echo("cPlayer::onCollision(%srcObject, %dstObject, %srcRef, %dstRef, %time:" SPC %time SPC ", %normal:" SPC %normal SPC", %contacts:" SPC %contacts SPC", %points:" SPC %points SPC ");"); } function cPlayer::onWorldLimit(%this, %limitMode, %limit) { // called when cPlayer object reaches World Limits // echo("cPlayer::onWorldLimit(%this, %limitMode, %limit);"); // echo("Hit" SPC %limit SPC "limit."); if(%this.key1 $= %limit ) { %this.ready = true; } } function cPlayer::onPositionTarget(%this) { // Called when target reaches moveTo destination // echo("cPlayer::onPositionTarget(%this);"); // echo("Position:" SPC %this.getPosition()); %this.ready = true; %this.updateMovement(); } function cPlayer::updateMovement(%this) { // echo("cPlayer::updateMovement();"); // echo("Ready:" SPC %this.ready SPC ", Key:" SPC %this.key1); if(%this.ready && %this.key1 !$= "") { %this.ready = false; $pos = %this.getPosition(); $X = (getWord($pos, 0) / %this.gridSize) * %this.gridSize; $Y = (getWord($pos, 1) / %this.gridSize) * %this.gridSize; echo("Position:" SPC $pos SPC "-" SPC $X SPC $Y); echo("Direction:" SPC %this.key1); switch$ (%this.key1) { case "top": $Y -= %this.gridSize; case "bottom": $Y += %this.gridSize; case "left": $X -= %this.gridSize; case "right": $X += %this.gridSize; default: // Note, moveTo's callback does not fire if you are already AT the target location %this.ready = true; } // echo("Target:" SPC $X SPC $Y); if($X != getWord($pos, 0) || $Y != getWord($pos, 1)) { // echo("moveTo:" SPC $X SPC $Y); %this.moveTo($X, $Y, %this.speed, true, true); } else { // echo("At target position, not moving."); $this.ready = true; } } } function cPlayer::addKey(%this, %key) { // Adds key to beginning of buffer %this.removeKey(%key); // echo("cPlayer::addKey(%this, " @ %key @ ");"); %this.key4 = %this.key3; %this.key3 = %this.key2; %this.key2 = %this.key1; %this.key1 = %key; } function cPlayer::removeKey(%this, %key) { // echo("cPlayer::removeKey(%this, " @ %key @ ");"); // removes key from buffer, and shifts later keys to the beginning switch$ (%key) { case %this.key1: %this.key1 = %this.key2; %this.key2 = %this.key3; %this.key3 = %this.key4; %this.key4 = ""; case %this.key2: %this.key2 = %this.key3; %this.key3 = %this.key4; %this.key4 = ""; case %this.key3: %this.key3 = %this.key4; %this.key4 = ""; case %this.key4: %this.key4 = ""; } } function playerUp() { // echo("playerUp();"); $player.addKey("top"); $player.updateMovement(); } function playerDown() { // echo("playerDown();"); $player.addKey("bottom"); $player.updateMovement(); } function playerLeft() { // echo("playerLeft();"); $player.addKey("left"); $player.updateMovement(); } function playerRight() { // echo("playerRight();"); $player.addKey("right"); $player.updateMovement(); } function playerUpStop() { // echo("playerUpStop();"); $player.removeKey("top"); $player.updateMovement(); } function playerDownStop() { // echo("playerDownStop();"); $player.removeKey("bottom"); $player.updateMovement(); } function playerLeftStop() { // echo("playerLeftStop();"); $player.removeKey("left"); $player.updateMovement(); } function playerRightStop() { // echo("playerRightStop();"); $player.removeKey("right"); $player.updateMovement(); }