PDA

View Full Version : help with a tiled game



big_b
04-06-2004, 11:28 AM
hi, im new to delphi and really need some help.

basically, i have a map thats layed out on my screen in tiles to produce a sort of overhead view of some corridoors and at the end is the goal the player is trying to reach.

ive coded in two ways of moving the character. Basically you can click and a tile and the character will move there but i dont know how to make it so the character can only move so far as one step infront of him.

so i opted for the movement to be based on the normal, up down left right keys. the guy moves and all but i wouldnt have a clue how to stop the guy from going through the tile that represents a wall. is this even possible? if its not please explain to me a better way of making my game.

thanks,
big_b

Harry Hunt
04-06-2004, 12:47 PM
I assume your map is some sort of two-dimensional array and the player character will move up/down/left/right in pixel-steps meaning he is not locked to your "tile grid".

If that is the case, it's pretty easy to make sure your character can't walk through walls. Whenever the player presses one of the arrow keys, your code should simply predict where the next step would take him and if he'd be moving into a wall, you'd simply ignore the keypress.

Here's an example

const
TileWidth = 32;
TileHeight = 32;
FloorTile = 0;
WallTile = 1;
var
PlayField: array[0..100, 0..100] of Integer;
PlayerX, PlayerY: Integer;
NewPlayerX, NewPlayerY: Integer;
begin
NewPlayerX := PlayerX;
NewPlayerY := PlayerY;
case Key of
VK_LEFT: Dec(NewPlayerX);
VK_RIGHT: Inc(NewPlayerX);
VK_UP: Dec(NewPlayerY);
VK_DOWN: Inc(NewPlayerY);
end;
if PlayField[NewPlayerX div TileWidth, NewPlayerY div TileHeight] = FloorTile then
begin
PlayerX := NewPlayerX;
PlayerY := NewPlayerY;
UpdateMap;
end
else
begin
PlaySound('Boing');
end;
end;


This isn't tested but it should work. Come back if you need more help :P

big_b
04-06-2004, 01:32 PM
ok well my code at the moment looks like this..

var
Form4: TForm4;
arr: array[0..9, 0..9] of integer =
((1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
(2, 2, 1, 1, 1, 1, 1, 1, 2, 2),
(2, 1, 1, 2, 2, 2, 2, 1, 1, 2),
(2, 1, 2, 2, 2, 2, 2, 2, 1, 2),
(2, 1, 1, 1, 1, 1, 1, 1, 1, 2),
(2, 1, 1, 1, 1, 1, 1, 1, 1, 2),
(2, 1, 2, 2, 2, 2, 2, 2, 1, 2),
(2, 1, 0, 1, 2, 2, 1, 0, 1, 2),
(2, 2, 1, 2, 2, 2, 2, 1, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2));

x: integer;
y: integer;


implementation

{$R *.dfm}



procedure TForm4.PaintBox1Paint(Sender: TObject);


begin
for x := 0 to 9 do begin
for y := 0 to 9 do begin
case arr[x, y] of

0: PaintBox1.Canvas.CopyRect(Rect(x*60, y*60, (x*60)+59,(y*60)+59),
BeerImg.Canvas,Rect(0,0,59,59));

1: PaintBox1.Canvas.CopyRect(Rect(x*60, y*60, (x*60)+59,(y*60)+59),
TileImg.Canvas,Rect(0,0,59,59));

2: PaintBox1.Canvas.CopyRect(Rect(x*60, y*60, (x*60)+59,(y*60)+59),
AsileImg.Canvas,Rect(0,0,59,59));

end;
end;
end;
end;




procedure TForm4.guy(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
mousex: integer;
mousey: integer;
blocked: boolean;

begin
mousex := X div 60;
mousey := Y div 60;
guyImg.Left := mousex * 60;
guyImg.Top := mousey * 60;




end;


procedure TForm4.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);

begin
blocked := guyImg.left-10;
if key = vk_up then guyImg.top:=guyImg.top-10;
if key = vk_right then guyImg.Left:=guyImg.Left+10;
if key = vk_down then guyImg.top:=guyImg.top+10;
if key = vk_left then guyImg.Left:=guyImg.Left-10;

end;

end.

basically i dont want the guy to go through the 2 tile. your code seems to something different to mine jsut by looking at it lol. so im confused. the first procedure in my code paints the map with a paint box. the second procedure is the movement via clicking which i dont really want to use so ignore that, and the third procedure is to just move the guy via the keys.

hopefully this will help you help me lol. thanks.

Paulius
04-06-2004, 02:15 PM
You wont get your game written for you, better try to understand Harry's idea. I'll try to rephrase what he meant: your map you called it arr (try making variable names as descriptive as possible, or you'll get really frustrated with larger programs) should contain not only tile image data but also if the tile is walkabe or not (better yet it should only contain tile ID, which you would use to look up tile information in another array), before moving your guy check if the tile he'll move to is walkable, if it is than move him, if not do nothing.

Harry Hunt
04-06-2004, 02:26 PM
The changes you have to make to your code are minimal.
In your KeyDown procedure instead of moving the player directly, check if he'd be walking into a wall and if that is the case, don't change his position.

The one line of code in my example that does the actual collision detection is this:


if PlayField[NewPlayerX div TileWidth, NewPlayerY div TileHeight] = FloorTile then ...


PlayField would be "arr" in your case, TileWidth and TileHeight would be two integer constants, in your case "60" and well, how to implement the NewPlayerX and NewPlayerY should be clear from the code in my previous post.


For the future: if you post your code here, try not to post entire programs. Also, if you post code the way you did, all the formatting will get lost so instead, place your code into [ pascal ] [ / pascal ] (without the spaces before and after the brackets).

big_b
04-06-2004, 10:25 PM
ok thanks, sorry about posting the entire code. im a noob lol. plus im not really that bothered about it being stolen. this is all just for an assignment and i not a very good programmer at all. lol. thansk again, ill be back if i cant get it to work or if i run into something else thats botherng me. :wink:

big_b
04-06-2004, 11:13 PM
ok sorry guys, i still cant get it to work. lol.

is the NewPlayerX and NewPlayerY my guyImg? :?

should i be using the copyrect command thingo to create my map? or is there a different way thats better?

thanks,
big_b

Harry Hunt
05-06-2004, 07:00 AM
I suppose guyImage is a TImage component?

NewPlayerX, NewPlayerY are just to integer variables.

PlayerX and PlayerY however would equal guyImage.Left and guyImage.Top.

CopyRect should work fine (if speed is not an issue).