Общее·количество·просмотров·страницы

воскресенье, 28 октября 2012 г.

Создание псевдотрехмерного движка

Конечно движок это через чур загнуто сказано,ну оно похоже на движок:)

Побудило меня на это то,что я фанат серии игра дум и ее модов,портов и т.д.(короче дум-задрот).меня всегда влекла атмосферность этой игры и еще со школы я мечтал написать свое вульфенштейно или думо подобное двигло.
Вот и зародились у меня некоторые темы.

Язык: Си.
Среда разработки: борланд Си 3.1

Поехали.

Итак движок будет под ДОС как вы поняли и рисоваться он будет методом рейкастинга.

В чем суть методики.

Это преобразование супер просто формы данных (в нашем случае обыкновенная матрица) в псевдотрехмерную проекцию с помощью пускания лучей из точки обзора в ее объем.

Выглядит это вот так:
на первом куске- двумерная карта и точка обзора откуда испускаются лучи,на втором куске трехмерная(псевдо) проекция.
Особенности в том,что стенки будут всегда перпендикулярны полу.за счет этого этот метод выигрывает в скорости,так как можно пускать один луч для всего столба экрана.
А так же стенки будут представлять собой равносторонние квадраты.

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

начнем писать код и походу дела его толковать.

из хидеров нам понадобится

#include<graphics.h>
#include<math.h>
#include<dos.h>
#include<conio.h>
#include<stdlib.h>

начальные переменные

float rad;
int scan, exitt=0,pres=0, speed=2, anglspd=3, curangl=-30;

тут понятно я думаю,скэн коды клавиш,выход,нажата клавиша,скорость движения по карте,скорость поворота в сторону,текущая позиция взгляда.

int KARTE[16][16]={
    {1,9,9,9,9,9,9,9,9,9,9,9,9,9,1},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,7,7,7,7,7,7,7,7,0,4},
    {9,0,0,0,0,7,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,7,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,7,7,7,7,7,7,7,7,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4}, 
     {9,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    };
вот и сама карта,она размерами 16х16.
мы находимся в точке которая помечена зеленым и смотрим в сторону где помечено красным.



карта это матрица(двумерный массив,который будет проектироваться в псевдотрехмерный мир)
каждая цифра отличная от 0 будет стеной (пола и потолка нет,я это спиздил у вульфенштэйна :D) и каждая цифра же одновременно окрашивает стену в цвет в соответствии с цветами драйвера EGAVGA.Bgi (его присутствие,к сожалению,необходимо).

Теперь что касается управления

void interrupt (*oldint9)(); // указатель на первичное прерывание клавиатуры
void interrupt newint9()

перехватываем int9 (прерывание клавиатуры) и в новом обработчике ставим свои кнопки управления(стрелки)

выглядит это следующим образом:

static int kbrdvalue;
 scan = inportb(0x60); // будем читать скэн-коды клавиш
   if(scan == 1)
 exitt = 1; // эск- выход
   else
   {
     if(scan == 72) // стрелки будут клавишами перемещения
 pres = 1;
     else
     {
       if(scan == 80)
  pres = 2;
       else
{
if(scan == 75)
pres = 3;
else
  {
  if(scan == 77)
pres = 4;

      else
  {
  pres = -1;
пояснение в комментариях.
так же нужно сделать сброс контоллера прерываний клавиатуры,процедурку я нашел в тырнетах:

kbrdvalue = inportb(0x61); // сбросим контроллер прерываний клавиатуры, т.к. мы не одни в системе (хотя это и ДОС)
 outportb(0x61, kbrdvalue | 0x80);
 outportb(0x61, kbrdvalue);
 outportb(0x20, 0x20);

начинаем основную часть:

initgraph(&gdriver, &gmode, "C:\\bc\\BGI"); // инициализируем графич.режим

xmax = getmaxx();
ymax = getmaxy();
rad = 3.1415926535897932384626433832795/180.0;
vlx = xmax/fov;

получаем размеры экрана.затем нам понадобятся радианы,ну и в конце по алгоритму значение vlx будет переходом от столбца к столбцу.
FOV как вы поняли это field of vision равное 60 градусам (можно поиздеваться с градусами и получить прикольные наркоманские эффекты):)

теперь установим наши прерывания 
oldint9 = getvect(9); // для установки первоначального значения получим вектор прерывания клавиатуры
setvect(9,newint9);

ну и основной цикл:

    for(angle = curangl; angle <= curangl+fov;angle++) // получаем угол (в градусах)

    {
    if(angle<0)
            tmpangl = angle + 360;
    else
         {
          if(angle>360)
                tmpangl = angle - 360;
          else
                tmpangl = angle;
          }

                          // вычисляем расстояние от нас до стенки (это тоже взято из алгоритма)
    xb = sin(angle*rad);       
    yb = cos(angle*rad);         
    bx = px;                 
    by = py;
    l = 0;
    xbtmp = xb;
    ybtmp = yb;

     do {
     bx = bx + xb; // находим первое ближайшее пересечение (т.к луч идет в квадрат и сталкивается с точками)
     by = by + yb;
     l = l + 0.5; // отображение стенок (можно регулировать отдаленность)
     fy = (int)by/10; // примерное наше расположение в квадрате (можно где то от 8 до 12, что бы не застрять в стенке) (как вы поняли каждое значение-это еще один квадрат)
     fx = (int)bx/10;
     k = KARTE[fx][fy];
   }while(k == 0);

   dd = (2*ymax) / l; //высоты столбца

   hp1 = ymax/2-dd; // находим верхние и нижние точки откуда сможем отрисовывать столбцы
   hp2 = ymax/2+dd;

   setfillstyle(1,k);
   bar(x,hp1,x+vlx,hp2); // рисуем двухмерными прямоугольниками
   setfillstyle(1,ceiling);
   bar(x,1,x+vlx,hp1-1);       //потолок
   setfillstyle(1,ground);
   bar(x,hp2+1,x+vlx,ymax);       //пол
   setlinestyle(SOLID_LINE, 1, 1); // окантовка-сплошная черная линия
   setcolor(0);
   line (x,hp1,x+vlx,hp1);
   line (x,hp2,x+vlx,hp2);
   x = x+vlx;


   }
   // тут просто- если нажали- изменяем координаты и углы
    if(pres == 1)
        {
    
         px = px +speed*xbtmp;
         py = py +speed*ybtmp;
       
        }
 if(pres == 2)
{
px = px - speed*xbtmp;
py = py - speed*ybtmp;
}

  if(pres == 3)
 curangl -= anglspd;

  if(pres == 4) 
curangl += anglspd;

  if(exitt == 1) // если выход- выполняем восстановления векторов прерываний и перевод в первоначальный режим экрана
   {
   disable();
            setvect(9,oldint9);
            kbrdvalue = inportb(0x61);
            outportb(0x61, kbrdvalue | 0x80);
            outportb(0x61, kbrdvalue);
            outportb(0x20, 0x20);
            enable();
            closegraph();
            exit(0);
            }
}


}



вот и все!)
вот как выглядит это кривое отродие:

Я думаю его немного улучшить, но думаю максимум на чем я закончу это что натяну на него текстуры и усе)))
в прочем хочется еще попробовать на паскале поколдовать,есть алгоритм по сложнее,но и двигло получается более-менее не квадратное,в общем посмотрим как пойдет.
ну и под конец думаю сделать очень простой двиг на delphi с opengl или D3D рендером.А пока вот что имеем,и то уверяю что писать такое не совсем просто.

Спасибо за внимание).






суббота, 20 октября 2012 г.

jelly bean 4.1.2

Итак друзья,вышла обнова андроид.теперь он получил ландшафтный режим ориентации.
Пысы : при обновлении слетает рУт,так что не забудьте его восстановить:-) 

четверг, 18 октября 2012 г.

Вшитие ассемблерного кода в проект на delphi через объектник

Итак ребята,по этому счету я не нашел практически ничего (мб разучился гууууглить?))).
бывает когда возможностей BASM не хватает,а писать все на низком уровне нет ни времени ни желания,особенно у тех кто работает с malware.

Поэтому есть прекрасная штука по вшитию ассемблерного кода.
Чем этот метод хорош:все идет в куче,не надо никаких библиотек таскать.

Итак:

;messagebox
.386
.model flat,stdcall
option casemap:none

include include\windows.inc
include include\kernel32.inc
include include\user32.inc

includelib lib\kernel32.lib
includelib lib\user32.lib


.data
mes db 'HOW ARE YOU?',0
tit db 'MASM',0

.code

public testproc

testproc proc

invoke MessageBox,0,addr mes,addr tit,0
invoke ExitProcess,0

testproc endp

end

так у нас выглядит исходник.он немного отличается от стандарта:
нету метки старт,public описывает идентификатор, как доступный из других модулей.
дальше оформляем любой код в процедуру.

делаем только ассемблирование, линковку не проводим.

на выходе получаем file.obj

теперь конвертируем его программой coff2omf (в конце поста ссылка на скачивание программ)

затем полученный объектник еще раз конвертируем в понимаемый для делфи через omf2d

все.осталось только подключить объектник к нашей программе.

перед implementation указываем ф-ю
function testproc: dword; stdcall;
а после implementation
подключаем командой {$L name.obj}
function testproc: dword; stdcall; external;

и вызываем просто как процедуру
конец:)

ссылка на скачивание программ
http://splashed.ucoz.ru/coff2omf_omf2d.rar

PS:
друзья блог открыт для анонимного комментирования,если есть какие то вопросы,оставляем комменты,по возможности отвечу:)

воскресенье, 14 октября 2012 г.

Интернет!!!

Ура господа!свершилось то что нексус имеет инет через модем!
Требуется только ppp виджет.в нем настраиваем ваш модем в соответствии с оператором и жмем подключить!
все пашет и так в бюджетном планшете мы имеем все те недостатки,как память и интернет)))


пятница, 12 октября 2012 г.

Подключение периферии к nexus 7

Сегодня получил USB host (пришлось заказать,в городе не продают)
удалось примонтировать флэшку на 8 гб.Думаю можно и больше,думаю даже внешний хард можно примонтировать.
Завтра попробую зайти в интернет через 3G модем.

Для тех кто собрался купить нексус,но его останавливает факт отсутствия модема-не парьтесь,выход есть.
Выход это вот такой девайс. вставляем симку-раздаем wifi.
аккумулятор на 1.5К мАч. думаю на 4-5 часов работы его хватит.
стоит такой аппарат 400-600 грн,что в общем то и не дорого,интернет всегда с собой в любой точке.



воскресенье, 7 октября 2012 г.