PDA

View Full Version : sprite is not drawn



leniz
23-05-2007, 02:14 PM
Hi,
I'm having a problem with my sprite not being drawn on screen. I create my sprite on dxtimer initialization or right after 'New Game' is pressed and I try to draw it on my doGame procedure, right after I finish my tiling, but alas... That stupid sprite won't even appear on my screen.
If anyone knows what's wrong with it, mI'm always open to ideas...

Thanks in advance
best regards, Leniz

FNX
23-05-2007, 02:27 PM
Hello leniz,
for problems like this you should kindly post a piece of your code, as i
think you've just started coding :)

Anyway, things to check are:

-Sprite.Visible := True;

-Sprite.Z must be higher than the tiled map Z (in case you used TBackgroundSprite)

-Try to init your sprites elsewhere like in DXDrawInitialize or FormCreate
or whatever

-Finally have a look to the samples coming with (un)DelphiX, there's much
to learn from

Hope this helps!

leniz
23-05-2007, 02:56 PM
i think you've just started coding :)
How did You know? :D

Here is my sprite creation:
with man do
begin
man.Image:=form22.dximagelist1.Items.Items[2];
man.Width:=man.Image.Width;
man.Height:=man.Image.Height;
man.Y:=53;
man.X:=944;
end;


And here I try to draw it:
procedure doGame;
....
//tiling stuff
form22.DXSpriteEngine1.Move(0);
form22.dxspriteengine1.Draw;
form22.DXSpriteEngine1.Dead;

Actually, half of the time I'm looking at those examples :)

FNX
23-05-2007, 03:30 PM
You should post the entire code here ;)

for example, is your man creation something like:

man := TImageSprite.Create(DXSpriteEngine.Engine)?

also, calling DxSpriteEngine.Move you should pass 1 or
LagCount if you want to go at same speed on every machine.

Be sure to set man's Z above the tile map.

If i remember to do it, tomorrow i'll post how i init stuff correctly.

leniz
25-05-2007, 03:49 PM
Ok, here is all the code I have:
unit gamestate3;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DXDraws, DXClass, dxsprite, DXInput;

type sprite = class(timagesprite)
public
procedure domove(movecount:integer); override;
end;

type TGameState = (gsStart, gsMenu, gsReset, gsGame, gsEndGame, gsGameOver, gsInstructions, gsEnd);

type
TMapTile = record
// Num : Byte; // number of tiles at one coordinate (allows stacking of tiles)
Tile : integer; // type of tile (0=grass, 1=path, etc.)
//Height : array[ 0..9 ] of Byte; // how tall the tile reaches
// Layer : array[ 0..9 ] of Byte; // used to make sure the sprites doesn't block.
// Walkable : boolean; // Whether the tile at this location is walkable
end;

TMap = array[0..32, 0..24] of TMapTile;

type
TForm22 = class(TForm)
DXDraw1: TDXDraw;
DXTimer1: TDXTimer;
DXImageList1: TDXImageList;
DXImageList2: TDXImageList;
DXSpriteEngine1: TDXSpriteEngine;
DXInput1: TDXInput;
procedure FormCreate(Sender: TObject);
procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure DXDraw1Initialize(Sender: TObject);
procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
private
{ Private declarations }
public
{ Public declarations }
procedure SetupMap(MapFile:string);
end;

const
mtiles = 3;
width = 32;
height = 24;

var
Form22: TForm22;
Points : word;
GameState : TGameState;
GameCounter : Integer;
MenuChoice : byte;
MenuImage : TDirectDrawSurface;
SelectorImage : TDirectDrawSurface;
InstructionImage : TDirectDrawSurface;
map:tmap;
tiles: array [0..mtiles] of tdirectdrawsurface;
man: sprite;




implementation

{$R *.dfm}


procedure doStart;
begin
// do the init stuff here, like loading images
// do the init stuff here, like loading images
menuImage:=TDirectDrawSurface.Create(Form22.DXDraw 1.DDraw);
menuImage.LoadFromGraphic(Form22.DXImageList1.Item s.Items[0].picture.Graphic);
SelectorImage :=TDirectDrawSurface.Create(Form22.DXDraw1.DDraw);
SelectorImage.LoadFromGraphic(Form22.DXImageList1. Items.Items[1].picture.Graphic);
SelectorImage.TransparentColor:=clblack;
menuChoice := 1;
GameState := gsMenu;
end;

procedure doMenu;
begin
// do menu stuff here
Form22.DXDraw1.surface.Draw(0,0,menuImage.clientre ct,menuImage,false);
Form22.DXDraw1.surface.Draw(246,256+(menuChoice-1)*142, selectorImage.clientrect,selectorImage,true);

end;

procedure doInstructions;
begin
// do Instructions stuff here
Form22.DXDraw1.surface.Draw(0,0,InstructionImage.c lientrect,InstructionImage,false);
end;

procedure doReset;

begin
// put the things before the game starts
// Form22.DXDraw1.surface.Canvas.Font.Color:=clred;
//Form22.DXDraw1.surface.Canvas.Brush.Style:=bsclear ;
man:=sprite.Create(form22.dxspriteengine1.engine);
with man do
begin
man.Image:=form22.dximagelist1.Items.Items[2];
man.Width:=man.Image.Width;
man.Height:=man.Image.Height;
man.Y:=53;
man.X:=944;
end;
GameState := gsGame;
end;


procedure doGame;
var x, y:byte;
begin
// put the game stuff in here
Form22.DXDraw1.surface.Fill(0);
for x := 0 to width do
begin
for y := 0 to height do
begin
form22.DXDraw1.Surface.Draw(x*32, y*32, tiles[map[x][y].tile].ClientRect, tiles[map[x][y].Tile], false );
end;
end;

with form22.DXDraw1.Surface.Canvas do
begin
brush.Style:=bsclear;
font.Size:=13;
font.color:=clred;
textout(10,0, 'FPS: ' + inttostr(form22.dxtimer1.FrameRate));
release;
end;
form22.DXSpriteEngine1.Move(0);
form22.dxspriteengine1.Draw;
form22.DXSpriteEngine1.Dead;
end;

procedure doEndGame;
begin
// do stuff here like freeing sprites
end;

procedure doGameOver;
begin
// do gameover stuff here like showing gameover message
end;

procedure doEnd;
begin
// do end stuff here like freeing images and all
Form22.DXTimer1.Enabled:=false;
menuImage.Free;
SelectorImage.Free;
instructionImage.Free;

// and finally close the game
Application.Terminate;

end;

procedure ProcessGamestate;
begin
case GameState of
gsStart : doStart;
gsMenu : doMenu;
gsInstructions :doInstructions;
gsReset : doReset;
gsGame : doGame;
gsEndGame : doEndGame;
gsGameOver: doGameOver;
gsEnd : doEnd;
end;
end;


procedure TForm22.DXDraw1Initialize(Sender: TObject);
var imgcnt:integer;
begin
Form22.DXTimer1.Enabled:=true;

for imgcnt := 0 to mtiles do
begin
tiles[imgcnt] := tdirectdrawsurface.create(form22.dxdraw1.DDraw);
tiles[imgcnt].loadfromgraphic(form22.DXImageList2.Items.Items[imgcnt].Picture.Graphic);
end;
GameState:=gsStart;
end;

procedure TForm22.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
inc(GameCounter);
try
ProcessGamestate;
except
dxtimer1.Enabled:=false;
messagedlg('An error has occurred',mterror,[mbok],0);
end;

dxdraw1.Flip;

end;

procedure TForm22.FormCreate(Sender: TObject);
begin
form22.setupmap('map1.map');
end;

procedure TForm22.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
begin
if key = vk_escape then
begin
case GameState of
// gsMenu : GameState := gsEnd;
gsInstructions : GameState := gsMenu;
gsGame : GameState := gsMenu;
gsGameOver : GameState := gsEndGame;
end;
end;

if (key = vk_return) and (GameState = gsMenu) then
begin
case menuChoice of
1 : GameState := gsReset;
2 : GameState := gsEnd;
end;
end;

if (key = vk_up) and (GameState = gsMenu) then
begin
if menuChoice = 1 then menuChoice := 2 else dec(menuChoice);
end;
if (key = vk_down) and (GameState = gsMenu) then
begin
if menuChoice = 2 then menuChoice := 1 else inc(menuChoice);
end;
end;
end;

procedure tform22.SetupMap(MapFile:string);
var stream:TFilestream;
C : Char;
x, y : Word;
tempbuffer : array[ 0..32, 0..24 ] of Char;
begin
Stream:=tfilestream.Create(mapfile, fmopenread);
try
try
for y:=0 to 24 do
begin
for x := 0 to 31 do
begin
stream.ReadBuffer(C, SizeOf(C));
tempbuffer[x][y] := c;
end;
end;
except on e:exception do
messagedlg(e.Message, mterror, [mbok], 0);
end;
finally
stream.free
end;

for y := 0 to 25 do
begin
for x := 0 to 32 do
begin
case tempbuffer[x][y] of
//grass
'0':
begin
map[x][y].Tile:=0;
end;
//path
'1' :
begin
map[x][y].Tile:=1;
end;
//water
'2' :
begin
map[x][y].Tile:=2;
end;
end;
end;
end;


end;

procedure sprite.domove(movecount: Integer);
begin
with form22.dxspriteengine1.Items.Find('man') do
begin
If (isUp in form22.DXInput1.States) Then man.Y:= man.Y -4;
If( isDown in form22.DXInput1.States) Then man.Y:= man.Y + 4;
If (isLeft in form22.DXInput1.States) Then man.x:= man.X - 4;
If (isRight in form22.DXInput1.States) Then man.X:= man.X + 4;
end;
end;

end.

Legolas
25-05-2007, 04:08 PM
Here's some stuff you could try to change:


man:=sprite.Create(form22.dxspriteengine1.engine);
with man do
begin // you don't need to repeat man
Image:=form22.dximagelist1.Items.Items[2];
Width:= Image.Width;
Height:= Image.Height;
Y:=53;
X:=944; // >> How wide is your window? Maybe your sprite is offscreen
end;



form22.DXSpriteEngine1.Move(0); // 0 stops all sprites. Look at sprite/basic delphix example


Another thing: have you assigned the DXDraw surface to your DXSpriteEngine component (look at DXDraw property of DXSpriteEngine component)?

leniz
25-05-2007, 04:28 PM
Yeah, I assigned the DXDraw an yes, my screen is wider than 994, but just in case, i lowered the value, but no success...

Legolas
25-05-2007, 05:16 PM
Ok, your doMove function is wrong. Replace it with


procedure sprite.doMove(MoveCount: Integer);
begin
inherited;

If (isUp in form22.DXInput1.States) Then man.Y:= man.Y -4;
If( isDown in form22.DXInput1.States) Then man.Y:= man.Y + 4;
If (isLeft in form22.DXInput1.States) Then man.x:= man.X - 4;
If (isRight in form22.DXInput1.States) Then man.X:= man.X + 4;
end;


then add DXInput1.Update in your doGame procedure:

procedure doGame;
var x, y:byte;
begin
// put the game stuff in here
Form22.DXInput1.Update;
Form22.DXDraw1.surface.Fill(0);

// ...big cut here...

form22.DXSpriteEngine1.Move(60); // look at the example!
form22.DXSpriteEngine1.Dead; // first check for dead sprites
form22.dxspriteengine1.Draw; // then draw them
end;


Then your last step:


man := sprite.Create(form22.dxspriteengine1.engine);
with man do
begin
Image:=form22.dximagelist1.Items[2]; // <<<<<<
Width:=Image.Width;
Height:=Image.Height;
Y := 53;
X := 944;
end;


...and it should work as expected :)

leniz
25-05-2007, 05:29 PM
...and it should work as expected :)
:D But this piece of cow dung still doesn't draw me a sprite...
I had it hard with only DXTimer, but now with gamestates - it's twice as painful.

Legolas
25-05-2007, 06:26 PM
...and it should work as expected :)
:D But this piece of cow dung still doesn't draw me a sprite...
I had it hard with only DXTimer, but now with gamestates - it's twice as painful.

That's strange! I just have copy'n'pasted your code and it works fine. If you want, put somewhere a zip file with your sources, and I'll try to catch the bug :)

leniz
25-05-2007, 06:47 PM
Thanks,
Here You are - one SFX file:
http://rapidshare.com/files/33362780/gamestate_project.exe
Let's hope You will do better than me...:D

Legolas
25-05-2007, 07:25 PM
So, your error is in the loop in DXDrawInitialize procedure. Your loop goes from 0 to mtiles, but in this way you are trying to access 4 tiles. In fact, you get an access violation error starting the game.

procedure TForm22.DXDraw1Initialize(Sender: TObject);
var imgcnt:integer;
begin
Form22.DXTimer1.Enabled:=true;

//for imgcnt := 0 to mtiles do
for imgcnt := 0 to mtiles - 1 do // <<<<< Here!!
begin
tiles[imgcnt] := tdirectdrawsurface.create(form22.dxdraw1.DDraw);
tiles[imgcnt].loadfromgraphic(form22.DXImageList2.Items[imgcnt].Picture.Graphic);
end;
GameState:=gsStart;
end;

leniz
25-05-2007, 07:30 PM
Oh thank You!
And to think that it would have saved me lots of time if I just had not ignored those errors... douh
Well thanks again. I'm sure it won't be the last time you save me :D

Legolas
25-05-2007, 07:37 PM
Oh thank You!
And to think that it would have saved me lots of time if I just had not ignored those errors... douh
Well thanks again. I'm sure it won't be the last time you save me :D

You are welcome ;)

Lesson 1: Never ignore access violation errors.
Lesson 2: Never forget "Lesson 1"

:mrgreen: