Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.02.2009, 09:05   #1
Stanislav
Квадрокоптерист
Участник клуба Подтвердите свой е-майл
 
Регистрация: 29.09.2007
Сообщений: 1,824
По умолчанию Делаю аркаду, нужна помощь... (Collision)

Доброе утро.

Довольно долгий промежуток времени ломаю голову над следующем кодом приведенный кажется Kostia.

Код:
  //если под ногами пусто, то падаем(проверяем 2 нижние точки(ноги))
  if (map[round(xp)div 16,round((yp+sy+16))div 16]<>'1')and
     (map[round(xp+15)div 16,round((yp+sy+16))div 16]<>'1') then
    sy:=sy+g
  else
  begin
    sy:=0;
    //прыжок
    if keypressed(32) then
      sy:=-6;
  end;
  if keypressed(39) then
    sx:=2;
  if keypressed(37) then
    sx:=-2;
  //если головой ударились, то польше не летим ввер, а начинаем падать
  if (map[round(xp)div 16,round((yp+sy))div 16]='1')or
     (map[round(xp+15)div 16,round((yp+sy))div 16]='1')then
    sy:=0;
  //если слево или справо стена, то не идем на таран
  if (map[round(xp+sx)div 16,round(yp+sy)div 16]='1')or
     (map[round(xp+sx)div 16,round(yp+sy+15)div 16]='1')or
     (map[round(xp+sx+15)div 16,round(yp+sy)div 16]='1')or
     (map[round(xp+sx+15)div 16,round(yp+sy+15)div 16]='1')then
    sx:=0;

  xp:=xp+sx;
  yp:=yp+sy;

  sx:=0;

  //проверим, нашел игрок конец уровня или нет
  if map[round(xp+8)div 16,round(yp+8)div 16]='3'then loadlevel;

  mapbmp.Canvas.FillRect(Rect(0,0,320,240));
  mapbmp.Canvas.Ellipse(round(xp-16),round(yp-16),round(xp),round(yp));
  for y:=1 to 15 do
    for x:=1 to 20 do
      case map[x,y] of
      '1': mapbmp.Canvas.Rectangle(x*16-16,y*16-16,x*16,y*16);
      '3': mapbmp.Canvas.Rectangle(x*16-12,y*16-12,x*16-4,y*16-4);
      end;
  form1.Canvas.Draw(0,0,mapbmp);
end;
Вопрос в следующем:

Наш "мяч":
Код:
  mapbmp.Canvas.Ellipse(round(xp-16),round(yp-16),round(xp),round(yp));
Я хотел изменить его разеры хотя бы до 32 т.е

Код:
  mapbmp.Canvas.Ellipse(round(xp-32),round(yp-32),round(xp),round(yp));
но при этом выше приведенная проверка уже не работает, перебрал уйму вариантов, но "мяч" пролетает сквозь стены..

во-общем то по коду не могу понять логики там, где выделил жирным, не могли бы в двух словах описать алгоритм работы указанного мной фрагмента?
Я часть той силы, что вечно хочет зла, но вечно совершает благо..

Последний раз редактировалось Stanislav; 03.02.2009 в 09:09.
Stanislav вне форума Ответить с цитированием
Старый 03.02.2009, 10:34   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Приведи полный код проги или пройди по шагам и выясни чему равны значения в условии.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 03.02.2009, 15:38   #3
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Обратите внимание допустим на запись
Код:
map[round(xp+sx) div 16,round(yp+sy) div 16]
Div - деление нацело, но на сколько? ... на 16, т.е. на размер спрайта минус 1, ...рационально вместо числа оставлять переменную, которая заполняется при загрузке спрайта, туда заносится размер спрайта минус 1.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 04.02.2009, 19:39   #4
Stanislav
Квадрокоптерист
Участник клуба Подтвердите свой е-майл
 
Регистрация: 29.09.2007
Сообщений: 1,824
По умолчанию

Спасибо всем я разобрался, но возник новый вопрос: в ниже приведеном коде размер спрайта равен размеру объекта т.е в даном случаи мяча, вопрос теперь в следующем как сделать что бы объект был скажем в два раза больше спрайта, точнее , как будет выглядить в этом случаи код проверки на столкновение? пример размер спрайта 16, объект 32..
делал div 32 работает столкновение с правой стеной, и полом... все остальное пролетает сквозь..

Код:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  g=0.5; //ускорение свободного падения

var
  Form1: TForm1;
  map: array[1..20,1..15]of char; //карта
  mapbmp: tbitmap; //буфер
  sx,sy: real; //скорость по x и y
  xp,yp: real; //позиция игрока на экране(в пикселах)


implementation

{$R *.dfm}

function keypressed(key: byte): boolean;
var
  keys: TKeyboardState;
begin
  result:=false;
  GetKeyboardState(keys);
  if(keys[key]=128)or(keys[key]=129)then result:=true;
end;

procedure loadlevel();
var
  f: TextFile;
  x,y: integer;
begin
  sx:=0; sy:=0;
  AssignFile(f,'level1.txt');
  Reset(f);
  for y:=1 to 15 do
    for x:=1 to 20 do
    begin
      if x<20 then
        read(f,map[x,y])
      else
        readln(f,map[x,y]);
      if map[x,y]='2'then
      begin
        xp:=x*16; yp:=y*16;
      end;
    end;
  CloseFile(f);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  loadlevel;
  mapbmp:=TBitmap.Create;
  mapbmp.Width:=320;
  mapbmp.Height:=240;
  mapbmp.Canvas.Brush.Color:=clWhite;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  x,y: integer;
begin
  //если под ногами пусто, то падаем(проверяем 2 нижние точки(ноги))
  if (map[round(xp)div 16,round((yp+sy+16))div 16]<>'1')and
     (map[round(xp+15)div 16,round((yp+sy+16))div 16]<>'1') then
    sy:=sy+g
  else
  begin
    sy:=0;
    //прыжок
    if keypressed(32) then
      sy:=-6;
  end;
  if keypressed(39) then
    sx:=2;
  if keypressed(37) then
    sx:=-2;
  //если головой ударились, то польше не летим ввер, а начинаем падать
  if (map[round(xp)div 16,round((yp+sy))div 16]='1')or
     (map[round(xp+15)div 16,round((yp+sy))div 16]='1')then
    sy:=0;
  //если слево или справо стена, то не идем на таран
  if (map[round(xp+sx)div 16,round(yp+sy)div 16]='1')or
     (map[round(xp+sx)div 16,round(yp+sy+15)div 16]='1')or
     (map[round(xp+sx+15)div 16,round(yp+sy)div 16]='1')or
     (map[round(xp+sx+15)div 16,round(yp+sy+15)div 16]='1')then
    sx:=0;

  xp:=xp+sx;
  yp:=yp+sy;

  sx:=0;

  //проверим, нашел игрок конец уровня или нет
  if map[round(xp+8)div 16,round(yp+8)div 16]='3'then loadlevel;

  mapbmp.Canvas.FillRect(Rect(0,0,320,240));
  mapbmp.Canvas.Ellipse(round(xp-16),round(yp-16),round(xp),round(yp));
  for y:=1 to 15 do
    for x:=1 to 20 do
      case map[x,y] of
      '1': mapbmp.Canvas.Rectangle(x*16-16,y*16-16,x*16,y*16);
      '3': mapbmp.Canvas.Rectangle(x*16-12,y*16-12,x*16-4,y*16-4);
      end;
  form1.Canvas.Draw(0,0,mapbmp);
end;

end.
Я часть той силы, что вечно хочет зла, но вечно совершает благо..
Stanislav вне форума Ответить с цитированием
Старый 04.02.2009, 23:24   #5
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

В этой простой игре работает древнее правило поколения 8-битных игр, заключающееся в том, что все объекты должны иметь одни и те же размеры спрайтов, прозрачность уберет лишнее, и позиционирование легко определяется через размеры.
Я в своих примерах в верхних темах "Уроки по созданию игр для новичков" и "Как вы относитесь к созданию игр на Delphi?" показывал пример универсальной системы позиционирования и перемещения объектов. Там совершенно не имеет значения какого размера спрайт, т.к. обработка идет в таймере и если нажаты какие-либо клавиши то тут идет сдвиг объекта, как только объект перешел максимальное смещение в текущей позиции, то считается, что он сменил клетку. Смещения назначаются в зависимости от размера клетки карты.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 05.02.2009, 00:21   #6
Stanislav
Квадрокоптерист
Участник клуба Подтвердите свой е-майл
 
Регистрация: 29.09.2007
Сообщений: 1,824
По умолчанию

Цитата:
Сообщение от Beermonza Посмотреть сообщение
В этой простой игре работает древнее правило поколения 8-битных игр, заключающееся в том, что все объекты должны иметь одни и те же размеры спрайтов, прозрачность уберет лишнее, и позиционирование легко определяется через размеры.
Я в своих примерах в верхних темах "Уроки по созданию игр для новичков" и "Как вы относитесь к созданию игр на Delphi?" показывал пример универсальной системы позиционирования и перемещения объектов. Там совершенно не имеет значения какого размера спрайт, т.к. обработка идет в таймере и если нажаты какие-либо клавиши то тут идет сдвиг объекта, как только объект перешел максимальное смещение в текущей позиции, то считается, что он сменил клетку. Смещения назначаются в зависимости от размера клетки карты.
Т.е я правильно понимаю что в даном конкретном случаи этого зделать нельзя?

А вы случаем говорили "Уроки по созданию игр для новичков" не об этом?


Код:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure WMPaint(var Message: TWMPaint);
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

// тип модели уровня
Type
  TGameMap = object
  //-----------------
  TGTexture: TBitmap; {текстура}
  TGMove:    Byte;    {проходимость: 1 - нельзя, 0 - можно}
  //-----------------
end;

var
  Form1: TForm1;
  BitBuf: TBitmap; // буфер построения кадра
  MapMas: array[0..39, 0..29] of TGameMap;  // скелет уровня
  x, y, cell: Byte;
  wall, brg: TBitmap; // для картинок

  // структуры для вывода изображения на форму
  M: TWMPaint;
  DC: THandle;
  PS: TPaintStruct;

implementation

{$R *.dfm}

// процедура вывода изображения на форму
procedure TForm1.WMPaint(var Message: TWMPaint);
begin
   DC:=Message.DC;
   If DC=0 then DC:=BeginPaint(handle,PS);
   Try
     BitBlt(DC,0,0,800,600,BitBuf.Canvas.Handle,0,0,SRCCOPY);
   Finally
      If Message.DC=0 then EndPaint(handle,PS);
   end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
// создается буфер кадра
  BitBuf:=TBitmap.Create;
  BitBuf.Width:=800;
  BitBuf.Height:=600;
// размеры формы
  Form1.Width:=800;
  Form1.Height:=600;
// размер клетки
  cell:=20;
// загрузка картинок
  wall:=TBitmap.Create;
  wall.LoadFromFile('wall.bmp');
  brg:=TBitmap.Create;
  brg.LoadFromFile('brg.bmp');

// простейшим образом создается уровень
  for y:=0 to 28 do
    begin
      for x:=0 to 39 do
        begin
          if (y=28)
             or ((y=25) and (x>=5) and (x<=10))
             or ((y=23) and (x>=15) and (x<=20))
             or ((y=21) and (x>=25) and (x<=30)) then
            begin
              // картинка мостика, "в нем" ходить нельзя
              MapMas[x,y].TGTexture:=brg;
              MapMas[x,y].TGMove:=1;
            end
          else
            begin
              // картинка заднего фона, ходить можно
              MapMas[x,y].TGTexture:=wall;
              MapMas[x,y].TGMove:=0;
            end;
        end;
    end;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
// запуск таймера
  Timer1.Enabled:=true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
// обновление кадра
  for y:=0 to 28 do
    for x:=0 to 39 do
      BitBuf.Canvas.Draw(x*cell,y*cell,MapMas[x,y].TGTexture);

// вывод изображения на экран      
  M.DC:=GetDC(handle);
  WMPaint(M);
  ReleaseDC(handle, DC);
  DeleteDC(DC);
end;

end.
Не подскажите как используя этот код осуществлять проверку и "хождение" объекта? не могу сообразить, буквально две строчки чтоб понять?

Спасибо.
Я часть той силы, что вечно хочет зла, но вечно совершает благо..
Stanislav вне форума Ответить с цитированием
Старый 05.02.2009, 16:08   #7
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Вышеуказанный тобой (буду на ты, так легче наверное будет в понимании) кусок - только создает уровень, если качал сам исходник, то можно посмотреть. Сейчас поищу код позиционирования... вот он: http://programmersforum.ru/showthrea...t=1206&page=17 пост #164
Один момент. Этот код универсален, в исходном варианте предназначен для перемещения по карте по двум осям X и Y и перемещение полустатичное, т.е. указан пункт назначения и объект туда "придет" в конце цикла перемещения. Что нужно изменить... вместо кода на смещение по-Y нужно вписать блок гравитации. Вместо определения через условия текущей точки и точки назначения следует вписать флаги клавиш (при нажатии какой-либо клавиши определенная переменная типа Boolean - True, при отпускании - False, или по-иному принципу).
Теперь как работает позиционирование. Допустим объект в клетке 1, и смещение его равно нулю, он в центре. Была нажата стрелка вправо, и удерживается, флаг клавиши - True, обработка перемещения выполняется. Каждый такт таймера к начальному смещению будет прибавляться число (в примере это единица, т.е. 1 пиксел), как только смещение перешло за предел полуразмера тайла, смещение обнуляется, объект теперь в клетке 2. Аналогично и в противоположную сторону. Теперь про столкновения. Если известны размеры спрайта объектов, их смещения и размеры одной клетки карты, то математикой можно определять расстояние между объектами, и при нулевом значении "тормозить" обоих. Мда, видимо сложновато на словах, постараюсь найти время и показать доработанный код.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 05.02.2009, 20:00   #8
Манжосов Денис :)
Участник клуба
 
Регистрация: 29.01.2008
Сообщений: 1,039
По умолчанию

В 4 посте есть такой код:
Код:
function keypressed(key: byte): boolean;
var
  keys: TKeyboardState;
begin
  result:=false;
  GetKeyboardState(keys);
  if(keys[key]=128)or(keys[key]=129)then result:=true;
end;
Мне не понятен смысл этой строчки кода:
Код:
if(keys[key]=128)or(keys[key]=129)then result:=true;
Объясните, пожалуйста.
Манжосов Денис :) вне форума Ответить с цитированием
Старый 05.02.2009, 22:13   #9
Stanislav
Квадрокоптерист
Участник клуба Подтвердите свой е-майл
 
Регистрация: 29.09.2007
Сообщений: 1,824
По умолчанию

Цитата:
Сообщение от Beermonza Посмотреть сообщение
Мда, видимо сложновато на словах, постараюсь найти время и показать доработанный код.

Я был бы весьма благодарен, действительно что то сложнавато для восприятия даже после трех кратного прочтения..


p.s простите за бестактный вопрос, но почему переименовали созданную мной тему? я ведь просто писал Collision, я как бы не пишу не какую аркаду.... спасибо
Я часть той силы, что вечно хочет зла, но вечно совершает благо..

Последний раз редактировалось Stanislav; 05.02.2009 в 22:28.
Stanislav вне форума Ответить с цитированием
Старый 05.02.2009, 23:23   #10
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Цитата:
Сообщение от Манжосов Денис :) Посмотреть сообщение
В 4 посте есть такой код:
Код:
function keypressed(key: byte): boolean;
var
  keys: TKeyboardState;
begin
  result:=false;
  GetKeyboardState(keys);
  if(keys[key]=128)or(keys[key]=129)then result:=true;
end;
Мне не понятен смысл этой строчки кода:
Код:
if(keys[key]=128)or(keys[key]=129)then result:=true;
Объясните, пожалуйста.
128 и 129 - код что клавиша с номером key нажата, а почему два значения? ...это учет четных и нечетных нажатий, т.е. после каждого нажатия код этот меняется поочередно то 128, то 129. Так же и на отпущенные клавиши, то 0 говорит о неактивности, то 1.

Цитата:
Сообщение от Stanislav
p.s простите за бестактный вопрос, но почему переименовали созданную мной тему? я ведь просто писал Collision, я как бы не пишу не какую аркаду.... спасибо
Ну дело в том, что тема эта гораздо обширнее станет по-видимому, и название обобщающее как нельзя кстати, надеюсь ты не против как автор темы?, да и сама цель наверное не ведет к простому интересу над кодом, в конце концов я думаю будет и итог - какая-нибудь аркадная игрушка.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 05.02.2009 в 23:26.
Beermonza вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
collision detection challengerr Gamedev - cоздание игр: Unity, OpenGL, DirectX 5 10.01.2009 20:53
Нужна помощь!!)) ТРОЯН=) Паскаль, Turbo Pascal, PascalABC.NET 2 29.12.2008 21:42
Нужна помощь BreeZe Помощь студентам 1 14.05.2007 21:38