Silnik
Od dłuższego czasu ludzie dręczą mnie wiadomościami e-mail jak i komentarzami na blogu dotyczącymi kiedy pojawi się tutorial o pisaniu silnika. Niestety, dawno temu o tym zapomniałem i raczej nie miałem zamiaru kontynuować pisania tego tutorialu jak i samego silnika. Aby móc napisać taki artykuł, trzeba najpierw stworzyć silnik, w chociaż bardzo prymitywnej wersji by potem opisać krok po kroku tworzenie go od początku. Ten i następny tydzień zadecydują, czy postanowię kontynuować projekt tego silnika. Jeśli tak, to poinformuję Was o tym na łamach mojego DevLog’a jak i gdy tylko będę miał wstępnie działająca wersje owego silnika rozpocznę pisanie tutoriali opisujących etapy jego produkcji. Jeśli okazałoby się jednak, iż nie będę miał w zamiarze kontynuować projekt, nie łamcie się. Wiem, iż w internecie nie ma takiego tutorial’a kompletnego. Oprócz mojego był jeszcze jeden który jakoś wyglądał ale niestety przestał być on rozwijany po pewnym czasie i tak naprawdę udostępniony kod nie pozwala na wykonanie niczego. Ja rozpoczynając pracę nad tym silnikiem też nie miałem żadnych tutoriali itp. Wszystko improwizowałem i myślę, ze sami też powinniście tak robić – zajmie to może dłużej, ale metodą prób i błędów dojdziecie do interesującego was rozwiązania które pozwoli stworzyć Wam Wasz własny silnik.
A więc, teraz tylko czekać do następnej niedzieli ;D
Sabaton, czyli wojna w kilku zdaniach
Cześć!
Wiem, że zapewne każdy z was spodziewał się tutaj posta o tworzeniu silnika ale niestety. Przez pisanie gry nie mam czasu na rozwijanie silnika, więc póki co raczej tutoriale się nie pojawią ale mam propozycję. Mogę wstawić tutaj link do pobrania aktualnej wersji silnika(o wiele bardziej rozbudowanej niż to co jest tu opisane), by każdy mógł na podstawie tego pisać własny. Zadecydujcie w komentarzach.
Ale przejdźmy do głównego tematu postu. Chciałem napisać także o czymś innym niż programowanie, więc napiszę o zespole Sabaton. Zapewne słyszeliście już o nim gdyż kiedyś, gdyż było o nim wiadomościach, ale dawno temu. Jest to szwedzki zespół śpiewający angielskie piosenki o brawurowo walczącej Polsce. Ich utwory „streszczają” wojnę, szczególnie tą widzianych oczami Polaków. Ich najlepsze według mnie piosenki to:
- 40:1 http://www.youtube.com/watch?v=0GmjeVrLEbA&feature=related
- Uprising http://www.youtube.com/watch?v=Mnxvdz65y8s
- Primo Victoria http://www.youtube.com/watch?v=zr8HRQ5TS8A&feature=related
Gorąco polecam ich piosenki wszystkim i na sam koniec zadaje sobie pytanie. Dlaczego oni nas tak lubią?
Dropbox
Cześć wszystkim
Nie pisałem już od dłuższego czasu, a w statystykach odwiedzin widzę, ze są tacy co jeszcze we mnie nie zwątpili. A więc, by ich nie zawieść napiszę jakiś nowy post. Będzie on dotyczył DropBox’a.
A cóż to takiego jest? DropBox to serwis umożliwiający trzymanie plików na serwerze. No ale przecież to nie żadna nowość, mógłby każdy rzec. No tak, ale DropBox, po zainstalowaniu klienta tworzy folder. Wszystko co wkleimy do tego folderu automatycznie znajdzie się w naszym folderze na serwerze. Klient DropBox’a automatycznie wgrywa pliki na serwer gdy tylko ulegną zmianie, jak i pobiera z serwera pliki gdy nie ma ich na komputerze. Klienta DropBox’a można zainstalować na kilku komputerach przypisując go do tego samego konta. Dzięki temu na każdym komputerze z którego korzystamy będziemy mieli bieżący dostęp do naszych danych. DropBox pozwala także udostępniać wybrane foldery znajomym.
Pełny opis możliwości DropBox’a znajduje się po tym adresem: https://www.dropbox.com/features
DropBox na start daje 2GB miejsca. Gdy ktoś zarejestruje się z naszego linku referującego i my i on otrzymamy 250MB dodatkowego miejsca na dane. I tak aż do 8GB. Za wykonanie 5 z 6 zadań otrzymanych od DropBox’a po założeniu konta możemy otrzymać dodatkowe 250MB. Sa to zadanie proste typu:
- Zainstaluj DropBox’a na komputerze
- Wklej jakiś plik do folderu DropBox’a itd.
Cały serwis jest bardzo dobrym pomysłem wiec zapraszam do rejestracji. Oczywiście, z mojego linku
: http://www.dropbox.com/referrals/NTEyMjA5OTUzOQ
Projekt
Tak jak obiecałem jakiś czas temu, wrzucam screeny z aktualnie prowadzonego przeze mnie projektu:
Model głównego bohatera:

Słoneczko:

Zastój
Cześć
Piszę po długiej przerwie, gdyż aktualnie nie mam za dużo czasu na pisanie. nie dość, ze w szkole skumulowały się sprawdziany, to jeszcze mam 2 końcowe sprawdziany w szkole muzycznej. Oprócz tego pisze grę. Jak na razie powiem tylko, ze jest to RPG w 3D. Więcej opisze później. Do tego na szybko od Niedzieli piszę program do wizualizacji algorytmów.
Więc niestety, tutorial z silnikiem się opóźni ale myślę, ze warto czekać.
Własny silnik w C++ – kod klasy Engine
Witam, w kolejnej części mojego artykułu o pisaniu własnego silnika w C++.
W tej części, tak jak napisałem ostatnio, zajmiemy się wypełnianiem klasy Engine kodem. Lecz, zanim to zrobimy, musimy wprowadzić lekką poprawkę do pliku engine.h. Mianowicie, należy zamienić linijkę:
na
i linię
na
Teraz, możemy się już zabrać za plik engine.cpp. Stwórzmy go i dodajmy do projektu. Zaczynamy od wypełnienia go deklaracjami:
//engine.cpp
/*********************************************************************/
#include „mainEngine.h”
_Engine Engine;
//Declaring hWnd to engine window
HWND Win32Window;
//Declaring font obejct
LPD3DXFONT g_pFont;
HFONT hFont;
Deklarujemy tutaj czcionkę a także uchwyt naszego okna. Oto dalszy kod pliku engine.cpp:
{
if(bits != 32 && bits != 16)
{
this->Error = incorrectBits;
return false;
}
HINSTANCE hWin32Inst = GetModuleHandle(NULL);
//Creating win32 window
WNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.lpfnWndProc = Win32Proc;
wc.hInstance = hWin32Inst;
wc.hbrBackground = reinterpret_cast(GetStockObject(NULL_BRUSH));
wc.lpszClassName = Win32WindowName;
//Registring class
if(!RegisterClass(&wc))
{
this->Error = classRegistration;
return false;
}
Win32Window = CreateWindowEx(WS_EX_CLIENTEDGE,Win32WindowName,appName,WS_POPUP | WS_VISIBLE,0,0,width,height,HWND_DESKTOP,NULL,hWin32Inst,NULL);
if(!Win32Window)
{
this->Error = createWindow;
return false;
}
//Creating Direct3D main object
Direct3D = Direct3DCreate9(D3D_SDK_VERSION);
if(!Direct3D)
{
DestroyWindow(Win32Window);
Win32Window = NULL;
this->Error = createDirect;
return false;
}
//Creating Direct3D device object
D3DPRESENT_PARAMETERS pp;
memset(&pp,0,sizeof(pp));
pp.BackBufferWidth = width;
pp.BackBufferHeight = height;
if(bits == 32) pp.BackBufferFormat = D3DFMT_A8R8G8B8; else pp.BackBufferFormat = D3DFMT_R5G6B5;
pp.BackBufferCount = 1;
pp.SwapEffect = D3DSWAPEFFECT_FLIP;
pp.EnableAutoDepthStencil = TRUE;
pp.AutoDepthStencilFormat = D3DFMT_D16;
if(sync) pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
else pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
DWORD flags;
if(hardware) flags = D3DCREATE_HARDWARE_VERTEXPROCESSING; else flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
Direct3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,Win32Window,flags,&pp,&Device);
if(!Device)
{
DestroyWindow(Win32Window);
Win32Window = NULL;
Direct3D->Release();
Direct3D = NULL;
this->Error = createDevice;
return false;
}
if(enableLights == true)
{
//Setting up the lights
Device->LightEnable(0,TRUE);
Device->SetRenderState(D3DRS_AMBIENT, 0xffffffff);
}
//Setting up Z buffer
Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
Device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
Device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
//Not use stencil buffer
Device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
//Setting up shade mode
Device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
//Setting up linear filltring
Device->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0,D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
Device->SetSamplerState(0,D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
//Setting up fonts
//hFont = CreateFont(0,0,0,0,FW_NORMAL,FALSE,FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, L”Arial”);
//D3DXCreateFont(Device, hFont, &g_pFont);
//Device->CreateVertexBuffer(sizeof(verts), D3DUSAGE_DYNAMIC, OURVERT_FVF, D3DPOOL_DEFAULT, &pVB, 0);
ShowCursor(showCursor);
return true;
}
O co chodzi w tym kodzie? Mianowicie, pierwsze linie, to sprawdzenie, czy jest odpowiednia głębia. Jeżeli tak, to przechodzimy dalej. Jeżeli nie – ustawiamy aktualny błąd na incorrectBits (ang. złe bity – zła głębia) i wyłączamy init silnika. Następnie kreujemy klasę okna(w przypadku nie powodzenia błąd classRegistration. Potem, tworzymy okno – niepowodzenie: błąd createWindow. Potem, czeka nas szybkie tworzenie głównego obiektu Direct3D(błąd: createDirect). Zaraz po tym tworzony jest device Direct3D(błąd: createDevice). To właśnie podczas kierowania device ustalana jest wielkość okna, flagi, formaty i wiele innych. Następnie uruchamiamy światła, ustawiamy współrzędną Z, wyłączamy stencil mode i ustawiamy shade mode. Na koniec linear filltring. W kodzie pojawia się też na koniec wykomentowana część – jest to tworzenie czcionki, czym nie będziemy się teraz zajmować. No i na sam koniec ustawienie wyświetlania kursora w zależności od tego, co podano w parametrze showCursor. To by było na tyle jeżeli chodzi o init silnika. Teraz jeszcze 5 pomniejszych metod. Oto ich kod:
{
Device->EndScene();
Device->Present(NULL,NULL,NULL,NULL);
}
void _Engine::Clear()
{
Device->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0xffffff00,1.0f,0);
}
void _Engine::BeginScene()
{
Device->BeginScene();
}
bool _Engine::Release()
{
if(pVB) pVB->Release();
pVB = NULL;
if(g_pFont!=NULL) g_pFont->Release();
g_pFont = NULL;
if(Device) Device->Release();
Device = NULL;
if(Direct3D) Direct3D->Release();
Direct3D = NULL;
if(IsWindow(Win32Window)) DestroyWindow(Win32Window);
Win32Window = NULL;
return true;
}
HWND _Engine::getHWND()
{
//We returning handle of our window
return Win32Window;
}
Myślę, że nie muszę ich wyjaśniać, gdyż są bardzo proste i nie zawierają dużo kod, lecz jeżeli chcecie, piszcie w komentarzach, a wyjaśnię wszystko dokładnie. No to teraz kompilacja! To wszystko jeżeli chodzi o tą część. W następnej, zaprezentuje kod pierwszej aplikacji wykorzystującej nasz silnik. Jeżeli chcecie, możecie spróbować napisać taką sami. Nie będzie z tym większego problemu.
Własny silnik w C++ – struktura i klasa Engine
Witajcie.
Tak, jak obiecywałem, piszę pierwszą część artykułu o pisaniu silnika 3D. A więc, do roboty!
Silnik będzie napisany w oparciu o bibliotekę statyczną, a więc musicie potrafić taką stworzyć. Jeżeli ktoś nie wie co i jak, polecam internetowy magazyn WARP(warp.nazwa.pl). W którymś numerze był bardzo fajny artykuł poświęcony bibliotekom statycznym, jak je tworzyć, i używać w programach.
Zaczniemy od stworzenia kilku podstawowych plików nagłówkowych:
- mainEngine.h
- Headers.h
- globalDeclarations.h
Jeżeli chcecie, możecie zmienić nazwy plików, tylko pamiętajcie, aby zamienić je potem również w kodzie!
Oto kod pliku Headers.h:
/*********************************************************************/
//Headers.h
/*********************************************************************/
//Win32 Headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <cstdio>
//C++ and C Headers
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
//DirectX Headers
#include <d3d9.h> // Direct3D
#include <d3dx9.h> // addtional Direct3D
#define DIRECTINPUT_VERSION 0×0900
//Namespaces
using namespace std;
//Extern Infos
extern HWND Win32Window;
extern LPD3DXFONT g_pFont;
extern HFONT hFont;
globalDeclarations.h:
//globalDeclarations.h
/*********************************************************************/
#include „Headers.h”
LRESULT CALLBACK Win32Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
const wchar_t Win32WindowName[] = L”Engine_render_wnd”;
const DWORD OURVERT_FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
typedef wchar_t WCHAR;
typedef CONST WCHAR *LPCWSTR;
#pragma comment (lib, „d3d9.lib”)
#pragma comment (lib, „d3dx9.lib”)
static IDirect3D9* Direct3D;
static IDirect3DDevice9* Device;
mainEngine.h:
//mainEngine.h
/*********************************************************************/
#include „globalDeclarations.h”
No, możemy być zadowoleni, ale do silnika jeszcze długa droga. Co znajduje się w poszczególnych plikach? A więc, plik mainEngine.h łączy wszystkie nagłówki z silnika, dlatego ten pliku musi zostać dołączony do każdego pliku cpp. W projekcie silnika, i każdej aplikacji wykorzystującej nasz silnik. Plik globalDeclarations.h dołącza plik Headers.h, deklaruje zmienne, obiekty i typy używane w silniku na skale globalną, jak i dołącza do silnika wszystkie potrzebne biblioteki. Ostatni plik, Headers.h dołącza do projektu silnika wszystkie nagłówki potrzebne silnikowi. Posiada on także extern ważniejszych obiektów globalnych.
W tej części artykułu, utworzymy jeszcze plik nagłówkowy engine.h który będzie posiadał główną klasę silnika. Metody klasy, zaprogramujemy w następnej części. A więc tworzymy nowy plik: engine.h. Dodajemy go do mainEngine.h dyrektywą #include.
#include „Engine\engine.h”
Kod podany wyżej zakłada, iż plik engine.h znajduje się w folderze Engine!
Oto kod pliku engine.h:
//engine.h
/*********************************************************************/
enum _Err
{
incorrectBits,
classRegistration,
createWindow,
createDirect,
createDevice
};
class Engine
{
public:
bool Init(wchar_t appName[],int width,int height,int bits,bool enableLights,bool showCursor,bool sync,bool hardware);
void Render();
void Clear();
void BeginScene();
bool Release();
HWND getHWND();
//——————————————————
_Err Error;
};
Omówmy klasę Engine. Jest to główna klasa silnika. Jej metody to:
- Init – inicjalizacja całego silnika
- Render – wyświetlenie wszystkich obiektów na ekranie
- Clear – wyczyszczenie buforu z aktualną klatką
- BeginScene – rozpoczęcie przyjmowania listy obiektów do wyświetlenia
- Release - deinicjalizacja całego silnika
- getHWND - pobranie uchwytu okna
Oprócz tego główna klasa silnika posiada zmienną Error posiadającej możliwość przyjmowania wartości typu _Err. Co to _Err? A więc, jest to aktualny błąd, jeżeli owa zmienna nie jest pusta, znaczy, że nastąpił błąd silnika. Jeden, z podanych w _Err. Wszystkie te błędy omówię, przy kodzie klasy Engine, gdyż łatwiej będzie nam je zrozumieć, gdy będziemy wiedzieć dlaczego występują!
To by było na tyle, jeżeli chodzi o pierwszą część! Do zobaczenia wkrótce!
Własny silnik w C++
Witajcie!
Nie pisałem od dawien dawna, lecz przeglądając statystyki, zauważyłem, iż nie opuściliście mojej strony
. A więc, aby pokazać, że strona nie upadła, piszę to. Większość, a raczej całość wpisów były tutaj o moim GameDev’ie i opisach projektów. Teraz będzie inaczej! Rozpoczyna się nowa era, w której pojawi się tu wiele wpisów o programowaniu. Powstała nawet na to specjalna kategoria. A żeby zacząć tryumfalnie, zapraszam na pierwszą część tutorial’a pod tytułem: „Własny silnik w C++„. Która pojawi się tutaj w ciągu najbliższych kilku godzin
.
Untitled
Tytuł nie mówi dzisiaj u mnie za wiele
. Jakoś nie miałem na niego weny. A z racji, iż dawno nie pisałem nic, należy to odrobić!
Co z „Grą”? A więc, chat, menu, lista serwerów, łączenie, mapy, lista graczy… To wszystko już jest gotowe. Lecz, nie zmienia to tego, że przede mną jeszcze dużo pracy! Ale mam czas, gdyż na mapę do pewnego projektu jeszcze sobie długo poczekam. Oprócz tego, grafik namawia mnie, żebym zaczął pisać FPS’a, który od dawana omawiamy. Chcieć mi się chce. Myśl o kolejnej grze i już próbując zasnąć obmyślam różnego rodzaju rozwiązania i algorytmy do gry. Jakieś ogólne założenia są, więc można by było od razu zabrać się do pisania, ale jeszcze pomyślę!
Gra i Gra Server
MatrixGadu – wczesna, lecz stabilna wersja tego pięknego komunikatora opartego o macierze została napisana! Projekt będzie się rozwijał powoli, lecz rozwijać się będzie. Nawet nie wiecie ile z takimi macierzami pracy! Ale nie o tym będę teraz pisał.
A więc o czym? Przeanalizujmy tytuł, gdyż one zawsze u mnie dużo znaczą. „Gra i Gra Server” – można go przyjąć dosłownie. Projekt, planowany od dość dawna, i pisany od jakiegoś czasu pod piękną nazwą „Gra”(tak robocza
) ruszył pełną parą! Ale w tytule widzimy też „Gra Server”. Otóż gra zakłada, iż będzie polegała na postawieniu sobie serwera, na którym wiele graczy będzie mogło grać – razem lub przeciwko sobie. Co z tym będzie, zobaczymy! Na razie wracam do pisania. Coś o tym co będziemy robić w grze? Może później.
Wszelkie pytania, jak i opinie, proszę umieszczać w komentarzach!