PDA

View Full Version : Strange problem with my game menu



aleksander_tenev
30-10-2006, 08:24 PM
I finish my game menu but there is one problem in the menu . I the menu you don't have mouse ,you choose start game or options or exit with arrows form keyboard and here is the problem . When i push up or down in the menu work only exit and options . I read my code but look like everythings is all right .
Here is the code for the game menu :

First i draw the logo start game , options and exit :

MenuImages.Items[0].Draw(DXDraw1.Surface,255,50,0) ; // Game Logo
DXDraw1.Flip;
// Draw Start New Game

MenuImages.Items[1].Draw(DXDraw1.Surface,350,300,0 );
DXDraw1.Flip;


//Draw Options

MenuImages.Items[2].Draw(DXDraw1.Surface,350,360,0 );
DXDraw1.Flip;

// Draw Exit

MenuImages.Items[3].Draw(DXDraw1.Surface,350,410,0 );
DXDraw1.Flip;


and here is the problem part - when i push up or down in the menu work only exit and options. (change the picture) and when i press random key from my keyboard then work start game :( very strange problem :)



procedure TMain.FormKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);

var Menuchoice : integer;

begin

Menuchoice:=1;

if key = vk_escape then begin Exit.ShowModal; if Exitg = 1 then close; end;

if key = vk_up then begin

if menuChoice = 1 then menuChoice := 3 else dec(menuChoice);
end;

if key = vk_down then begin

if menuChoice = 3 then menuChoice := 1 else inc(menuChoice);
end;

Case Menuchoice of
1 : begin MenuImages.Items[4].Draw(DXDraw1.Surface,350,300,0 );
DXDraw1.Flip; end;
2 : begin MenuImages.Items[5].Draw(DXDraw1.Surface,350,360,0 );
DXDraw1.Flip; end;
3 : begin MenuImages.Items[6].Draw(DXDraw1.Surface,350,410,0 );
DXDraw1.Flip; end;
end;


end;

grudzio
30-10-2006, 10:09 PM
Its because menuchoice variable is declared in TMain.FormKeyUp event.
Each time this event is called menuchoice is set to 1. If down arrow is pressed then menuchoice is 2, if up arrow then menuchoice equals 3. If any other key except ESC is pressed then menuchoice still equals 1. Also note that condition

if menuchoice = 3 then ... is never reached.

To fix it declare menuchoice as global or as a field of TMain Form nad set it
to zero during TMain.OnCreate event (or any other initialisation procedure you use). Your TMain.OnKeyUp event will look something like this:



procedure TMain.FormKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);

begin


if key = vk_escape then begin
Exit.ShowModal;
if Exitg = 1 then close;
end;


// no if's just modulo divisions
if key = vk_up then
MenuChoice := (MenuChoice - 1) mod 3;
if key = vk_down then begin
MenuChoice := (MenuChoice + 1) mod 3;

Case Menuchoice of
0 : begin MenuImages.Items[4].Draw(DXDraw1.Surface,350,300,0 );
DXDraw1.Flip;
end;
1 : begin MenuImages.Items[5].Draw(DXDraw1.Surface,350,360,0 );
DXDraw1.Flip;
end;
2 : begin MenuImages.Items[6].Draw(DXDraw1.Surface,350,410,0 );
DXDraw1.Flip;
end;
end;


end;



I also think that more natural would be to place this menu code in TMain.OnKeyDown event.

Edit: code correction.

Traveler
30-10-2006, 11:08 PM
Its a good habit, to place code that draws something, in procedures that are meant for drawing. The FormKey Up event is used for handling input.
As such you should only change the variable Menuchoice in there.

As for your question, from what I understand is that your menu only works with the items 'options' and 'exit'. This is because in your code you say that menuChoice should become 1 when Down is pressed and menuChoice is equal to 3. Therefor only two values work: 1 and 2. In your case probably exit and options.


Also, if I may give you another tip...

Take a look at those if statements and check for a pattern. See how you keep repeating those ifs? Your code would be much cleaner if you placed all that in a case block.


case key of:
vk_up : ;
vk_down : ;
vk_escape : ;
end;


Hope that helps a bit.

PS, are you by any chance the one that emailed me about a menu? I read an email earlier today (received on saturday) about a similar issue, but I didn't get around to answering it yet.

aleksander_tenev
31-10-2006, 06:58 AM
are you by any chance the one that emailed me about a menu? I read an email earlier today (received on saturday) about a similar issue, but I didn't get around to answering it yet.

Yes, and i almost finish my game menu if you wish i will send to you my source.

One more thing :
How can i disable DXDraw because when i push up or down in the menu the objects Start Game or Options or Exit (now they work ) blink/vibrating
(i don't know what is correctly to say) just like turn on/off the lamp

Sorry for awful english :( . I learned english in internet :) .

Traveler
31-10-2006, 09:36 AM
[quote="aleksander_tenev"]
One more thing :
How can i disable DXDraw because when i push up or down in the menu the objects Start Game or Options or Exit (now they work ) b]

If I understand you correctly, I think the flickering is caused by the extra DXDraw1.Flip; in the FormKeyUp procedure.
I can't tell for sure though. I'd have give the source a closer look.

In regards to using a mouse, just check for the coordinates of the menuitems.


procedure TForm1.DXDraw1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if &#40;x > 150&#41; and &#40;x < 250&#41; and &#40;y > 50&#41; and &#40;y < 100&#41; then menuChoice = 1;
if &#40;x > 150&#41; and &#40;x < 250&#41; and &#40;y > 150&#41; and &#40;y < 150&#41; then menuChoice = 2;
end;

I should warn you though, this is not very OOP. If you want to do it the right way. You should make every menu item an object and have each object deal with it's own mouse functions, much like the buttons in the vcl.

grudzio
31-10-2006, 09:52 AM
You don't have to disable DXDraw. Just do as Traveler suggested. Move drawing code form OnKeyUp event to separate Draw procedure. (procedure you do all the drawing). When you draw in OnKeyUp event the selected menu is drawn only once which causes this blink.

Another suggestion. You don't have to call DXDraw.Flip each time you draw something. Call it only once after everything is already drawn. To make it more clear here is an example code



// This is not the best example of an efficient drawing procedure
// because one menu item is drawn twice - first time as normal
// and second as selected. I did it like this to make it as simple
// as possible.
procedure TMain.Draw;
begin
// Game Logo
MenuImages.Items&#91;0&#93;.Draw&#40;DXDraw1.Surface,255,50,0&#41; ;

// Draw Start New Game
MenuImages.Items&#91;1&#93;.Draw&#40;DXDraw1.Surface,350,300,0 &#41;;

//Draw Options
MenuImages.Items&#91;2&#93;.Draw&#40;DXDraw1.Surface,350,360,0 &#41;;

// Draw Exit
MenuImages.Items&#91;3&#93;.Draw&#40;DXDraw1.Surface,350,410,0 &#41;;

//Draw selected menu
Case Menuchoice of
0 &#58; MenuImages.Items&#91;4&#93;.Draw&#40;DXDraw1.Surface,350,300,0 &#41;;
1 &#58; MenuImages.Items&#91;5&#93;.Draw&#40;DXDraw1.Surface,350,360,0 &#41;;
2 &#58; MenuImages.Items&#91;6&#93;.Draw&#40;DXDraw1.Surface,350,410,0 &#41;;
end;
//the flip is called when everything is drawn
DXDraw1.Flip;
end;

I hope it helps.

aleksander_tenev
01-11-2006, 11:33 AM
Thanks