Czemu podany kod Działa? Prawdopodobne wykroczenie poza zakres tablicy.

0

Mam taki kod:

var
  SpecialKeys : array[0..20] of boolean;

procedure SpecialKeyDown(Key : Integer; X, Y : longint); cdecl;
begin
  SpecialKeys[Key] := true;
end;

procedure SpecialKeyUp(Key : Integer; X, Y : longint); cdecl;
begin
  SpecialKeys[Key] := false;
end; 

function GetSpecialKey(Key : Integer) : Boolean;
begin
  result := SpecialKeys[Key]
end;                                            


procedure Keyboard;
begin
  if GetKey(27) then Halt(0);
  if GetSpecialKey(GLUT_KEY_UP) then GameObject.Y := GameObject.Y + 0.01;
  if GetSpecialKey(GLUT_KEY_DOWN) then GameObject.Y := GameObject.Y - 0.01;
  if GetSpecialKey(GLUT_KEY_LEFT) then GameObject.X := GameObject.X - 0.01;
  if GetSpecialKey(GLUT_KEY_RIGHT) then GameObject.X := GameObject.X + 0.01;
  if GetSpecialKey(GLUT_KEY_INSERT) then
  begin
    GameObject.X := 0;
    GameObject.Y := 0;
    GameObject.Angle := 0;
  end;
end;

Begin
  // Inne callbacki;
  glutSpecialFunc(@SpecialKeyDown);
  glutSpecialUpFunc(@SpecialKeyUp);
  // MainLoop
end;

Jak widać Tablica SpecialKeys ma rozmiar od 0 do 20 przy czym wartość GLUT_KEY_INSERT to 108. A mimo wszystko kod się nie wysypuje i wszystko działa poprawnie. Ktoś może mi to wytłumaczyć?

0

SpecialKeys przypadkiem trafia ci tuż przed jakaś dużą tablicą, na razie niezbyt używaną w twoim programie.

0

Dobra mam coś takiego:

unit gEngine_Keyboard;

{==============================================================================}

{$mode objfpc}{$H+}

{==============================================================================}

interface

{==============================================================================}

uses
  Classes, SysUtils;

{==============================================================================}

var
  Keys        : array[0..255] of boolean; // Tablica przechowująca stan klawiszy (true - wciśnięty, false - niewciśnięty)
  SpecialKeys : array[0..20] of boolean;  // Tablica przechowująca stan specjalnych klawiszy (F1-F12 itp) (true - wciśnięty, false - niewciśnięty)

  SpecialKeyPressed : boolean;            // Zmienna przechowująca informacje czy naciśnięto specjalny klawisz.
  NormalKeyPressed  : boolean;            // Zmienna przechwująca informacje czy naciśnięto normalny klawisz.

{==============================================================================}

procedure KeyDown(Key : Byte; X, Y : Integer); cdecl;
procedure KeyUp(Key : Byte; X, Y : Integer); cdecl;
procedure SpecialKeyDown(Key : Integer; X, Y : longint); cdecl;
procedure SpecialKeyUp(Key : Integer; X, Y : longint); cdecl;
function GetKey(Key : Integer) : Boolean;
function GetSpecialKey(Key : Integer) : Boolean;
procedure ClearKeys;

{==============================================================================}

implementation

{==============================================================================}

// Callback do glutKeyboardFunc.
//--------------------------
procedure KeyDown(Key : Byte; X, Y : Longint); cdecl;
begin
  Keys[Key] := true;
  NormalKeyPressed := true;
  SpecialKeys[Key] := false;
  SpecialKeyPressed := false;
end;

{------------------------------------------------------------------------------}

// Callback do glutKeyboardUpFunc.
//----------------------------
procedure KeyUp(Key : Byte; X, Y : Longint); cdecl;
begin
  Keys[Key] := false;
  NormalKeyPressed := false;
  SpecialKeys[Key] := false;
  SpecialKeyPressed := false;
end;

{------------------------------------------------------------------------------}

// Callback do glutSpecialFunc.
//-----------------------------
procedure SpecialKeyDown(Key : Integer; X, Y : longint); cdecl;
begin
  SpecialKeys[Key] := true;
  SpecialKeyPressed := true;
  Keys[Key] := false;
  NormalKeyPressed := false;
end;

{------------------------------------------------------------------------------}

// Callback do glutSpecialUpFunc.
//-----------------------------
procedure SpecialKeyUp(Key : Integer; X, Y : longint); cdecl;
begin
  SpecialKeys[Key] := false;
  SpecialKeyPressed := false;
  Keys[Key] := false;
  NormalKeyPressed := false;
end;

{------------------------------------------------------------------------------}

// Pobiera stan klawisza "Key".
//-----------------------------
function GetKey(Key : Integer) : Boolean;
begin
  result := Keys[Key]
end;

{------------------------------------------------------------------------------}

function GetSpecialKey(Key : Integer) : Boolean;
begin
  result := SpecialKeys[Key]
end;

{------------------------------------------------------------------------------}

// Ustawia stan wszystkich klawiszy na niewciśnięte.
//--------------------------------------------------
procedure ClearKeys;
var
  i : Byte;
begin
  for i := 0 to 255 do
    Keys[i] := false;
  for i := 0 to 20 do
    SpecialKeys[i] := false;
end;

{==============================================================================}

end.

Jak zakomentowałem wszystko co dotyczy tablicy Keys (procedury funkcje itp). To kod dalej działał. Wykrywał poprawnie wszystkie specjalne klawisze których wartość przekracza 20.

GLUT_KEY_LEFT: 100
GLUT_KEY_UP: 101
GLUT_KEY_RIGHT: 102
GLUT_KEY_DOWN: 103
GLUT_KEY_PAGE_UP: 104
GLUT_KEY_PAGE_DOWN: 105
GLUT_KEY_HOME: 106
GLUT_KEY_END: 107
GLUT_KEY_INSERT: 108

Niby skoro działa to mógłbym zostawić ale chciałbym wiedzieć czemu działa mimo, że niby nie powinno.

2

Bo nadpisujesz jakieś dane znajdujące się w pamięci za tą tablicą - być może akurat tak wypada, że jest to nieużywany obszar (np.dzięki paddingowi).
Nie powinieneś na tym polegać i istnieje spora szansa, że jeżeli np.zmienisz kolejność modułów w uses, ten kod radośnie zaprzestanie działania.

0

Ok dzięki. Już mam to poprawione jednak i tak chciałem znać odpowiedź.

1
SpecialKeys : array[GLUT_KEY_LEFT..GLUT_KEY_INSERT] of boolean;

1 użytkowników online, w tym zalogowanych: 0, gości: 1