PDA

View Full Version : Another question on tiled maps



neafriem
17-06-2004, 09:55 AM
I have map my characters nonflickering with the method that are showed on the ye olde page. With sprites, masks and drawing them on a bufferbox and then copy it to a weiving box. But I have now a big problem, because I want to use a tiled map as the background, but it has to be a bitmap to work. How can you fix this. I tried to drawing the tilde map in another paintbox then copy that in the bufferbox as the background. Then it became flickerless but when you moved the charcter then all the previous posistions also was visible so you got a long serpent of the same dude. Can anyone help me please.

Alimonster
17-06-2004, 11:40 AM
Post some code dude...

Traveler
17-06-2004, 12:41 PM
Sounds like your drawing routine needs some work.

But like Alimonster said, give us some code

neafriem
20-06-2004, 12:45 PM
this is no good code, its my first game ever, so be nice

:( :

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, jpeg;

const
SpriteWidth : Integer = 28;
Screenwidth : Integer = 640;
StartWidth : Integer = 55;
WorldHeight : Integer = 680;
WorldWidth : Integer = 680;

type
TForm1 = class(TForm)
seebox: TPaintBox;
trollkarltimer: TTimer;
trollkarl: TImage;
trollkarlmask: TImage;
trollkarlh: TImage;
trollkarlhmask: TImage;
trollkarlv: TImage;
trollkarlvmask: TImage;
bufferbox: TImage;
trollkarlupp: TImage;
trollkarluppmask: TImage;
trollkarlner: TImage;
trollkarlnermask: TImage;
movetimer: TTimer;
tree: TImage;
bush: TImage;
grass: TImage;
mapbox: TPaintBox;
Background: TImage;
Timer1: TTimer;
Worldbox: TPaintBox;
SeeWorldBox: TPaintBox;
procedure FormCreate(Sender: TObject);
procedure trollkarltimerTimer(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure movetimerTimer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure mapboxPaint(Sender: TObject);
private
{ Private declarations }

AreaRect : TRect;

MapRect : TRect;

PlayerRect: TRect;
PlayerMaskRect: TRect;

StartX : Integer;
StartY : Integer;

PlayerStartPosX : Integer;
PlayerStartPosY : Integer;

// spelare 1
function BlueRect( X, Y: Integer ): TRect;

public
{ Public declarations }
end;

var
Form1: TForm1;
Xaxis,Yaxis : integer;
Playermove : Integer;
oldwidth, oldheight : integer;
vis : boolean;

arr: array[0..16, 0..16] of integer =
((1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1),
(1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1),
(1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1),
(1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0),
(0, 2, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2),
(0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0),
(0, 2, 1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 1, 0, 0),
(0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0),
(0, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0),
(0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0),
(0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
(0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
(0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
(0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
(0, 2, 0, 1, 2, 0, 2, 0, 0, 1, 2, 0, 1, 0, 0, 0, 0),
(2, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
(2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0));


implementation

{$R *.DFM}

function SetScreenResolution(Width, Height: integer): Longint;
var
DeviceMode: TDeviceMode;
begin
with DeviceMode do begin
dmSize := SizeOf(TDeviceMode);
dmPelsWidth := Width;
dmPelsHeight := Height;
dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
end;
Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
vis := true;
// Fixa Fullscreen
OldWidth := GetSystemMetrics(SM_CXSCREEN);
OldHeight := GetSystemMetrics(SM_CYSCREEN);
SetScreenResolution(640, 480);
form1.Formstyle:=FSStayOnTop;
form1.borderstyle:=bsNone;
form1.left := 0;
form1.top := 0;
form1.width := screen.width;
form1.height := screen.height;
// Slut

// StartvA¤rden pA¥ variabler
Randomize;
PlayerStartPosX := 0;
PlayerStartPosY := 318;
StartX := 5;
StartY := 334;
Playermove := 3;
Xaxis := 0;
Yaxis := 0;
// Slut

// StA¤lla in storleken pA¥ Buffer- och Seebox
Bufferbox.Width := WorldWidth;
Bufferbox.Height := WorldHeight;
Seebox.Width := WorldWidth;
Seebox.Height := WorldHeight;


// Background
AreaRect := Rect(0,0,Screen.Width, Screen.Height);

//The Map
MapRect := Rect(0,0,Screen.Width,Screen.Height);
// The player
PlayerRect := Rect(0,0,SpriteWidth,trollkarl.Height);
PlayerMaskRect := Rect(0,0,SpriteWidth,trollkarl.Height);
end;

// The player
function TForm1.blueRect(X, Y: Integer):TRect;
begin
Result := Rect(X,Y,X+SpriteWidth,Y+trollkarl.Height);
end;

procedure TForm1.trollkarltimerTimer(Sender: TObject);
begin
// Backgrundens Buffer
BufferBox.Canvas.CopyMode := cmSrcCopy;
BufferBox.Canvas.CopyRect(AreaRect, background.Canvas, AreaRect );

// spelarens buffer
BufferBox.Canvas.CopyMode := cmSrcAnd;
BufferBox.Canvas.CopyRect(BlueRect(StartX,StartY),
trollkarlmask.Canvas, PlayerMaskRect );

BufferBox.Canvas.CopyMode := cmSrcPaint;
BufferBox.Canvas.CopyRect(BlueRect(StartX,StartY),
trollkarl.Canvas, PlayerRect );

SeeBox.Canvas.CopyMode := cmSrcCopy;
SeeBox.Canvas.CopyRect(AreaRect,
BufferBox.Canvas, AreaRect );

// World buffer
WorldBox.Canvas.CopyMode := cmSrcCopy;
WorldBox.Canvas.CopyRect(MapRect, Mapbox.Canvas, MapRect );


SeeWorldBox.Canvas.CopyMode := cmSrcCopy;
SeeWorldBox.Canvas.CopyRect(MapRect,
WorldBox.Canvas, MapRect );

Harry Hunt
20-06-2004, 01:15 PM
Your codes is really hard to read because when you posted it, all the formatting got lost. Next time put your code between [ pascal ] [ /pascal ] (there's a button above the text field) to make sure the formatting is preserved.

A few things:
Using a TImage component as back-buffer is overkill. Use a TBitmap instead that you create dynamically in OnCreate and free in OnClose.

You will only need one target canvas (either that of a TPaintBox or even your form's canvas) and one back-buffer. You can have more than one buffer, but one is enough to get everything flicker free.

The mask-system to achieve transparency works but there's an easier method. Let's say Image1 holds a sprite that you want to be transparent. Then try this:


// Upon program initialization
Image1.TransparentColor := clFuchsia; //Whatever;
Image1.Transparent := True;

// Actual drawing
PaintBox1.Canvas.Draw(0, 0, Image1.Picture.Bitmap);

This will give you transparency without having to worry about masks.


The "proper" way of working with a back-buffer is:

1.) Clear the backbuffer (might not be necessary if tiles fill the entire buffer)
2.) Draw the tiles onto the buffer (back to front)
3.) Draw the sprites onto the buffer
4.) Draw the buffer onto the target-canvas

neafriem
20-06-2004, 08:11 PM
Thanks for the tips. I will remember the thing with the code. I didn't know that. Sorry. Can you say if I have understood this correctly, You have to make every image for the tiled map with a "wierd" background color so you make it trasperant. That you handle the map as a usual image. Thanks agian.

neafriem
20-06-2004, 08:24 PM
When I used the code
// Upon program initialization
Image1.TransparentColor := clFuchsia; //Whatever;
Image1.Transparent := True;
then when I tried to compile it it was a error : " Undeclared idetifier. 'TransparentColor'. Why?

Harry Hunt
20-06-2004, 08:37 PM
oops, my bad...
Image1.Picture.Bitmap.TransparentColor := clFuchsia;
Image1.Picture.Bitmap.Transparent := True;

It's a property of the bitmap. Not of the image.
Make sure you use a lossless image format for all your transparent images. If you were to use JPEG compression, the compression artefacts would spill into the transparent areas and the transparency wouldn't work properly.

Transparency basically is achieved by replacing a solid color in an image with the background you draw it on. It's important that you pick a color that you definitely won't use in the non-transparent parts. I like to use Fuchsia (255, 0, 255) because it's an extremely ugly color.

If you have further questions, let me know.

Harry Hunt
20-06-2004, 08:40 PM
Actually the TImage component as well as the TBitmap object can determine the transparent color itself provided that the bottom left-most pixel in your image has that color.
In that case, you'd just do this:

Image1.Transparent := True;

neafriem
20-06-2004, 08:56 PM
thanks