From YYpBD's MediaWiki
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[318] 제 목 : [강좌] dx강좌-0(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 15:50:05 읽음 : 152 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
안녕 하십니까(-_- 안녕못하시다면 안녕 해버리세여 쿠하하하--)
드디에 아기다리 고기다리던!(정말?) ddraw강좌가.. 나오게되씁니다..
우선.. 요번강좌에서 다루게 될내용은.. ddraw의 초기화에 관한 것입니다.
말그대로 가장기초가 되는 부분이므로 숙지하시기 바랍니다.
(나중에 제가 제공하게될 라입에 초기화함수가있으니 머.. 대충만알아두셔도-_-)
그리고 제가 하게될 강좌는 dx7.0을 기본으로 합니다 고로 자료실에 있는directx7.0 헤더 파일을 받으셔야 합니다
(그리고 이강좌는 풀스크린 모드를 기초로 합니다.)
사설이 길었네요.. 그럼 시작합시다!(그리고 중간중간 반말이
튀어나올쑤있으므로 인내심 좋은분들이 보심이 좋겠습니다 ..마끼시러ㅠ.ㅠ)
-----------------------------------------------------------------------
1. 다이렉트 드로우의 기초!
다이렉트 드로우란 무엇이냐 말그대로 화면에 그림 팍그리삐는기라! 죠 -_-
그럼.. 다이렉트드로우는 어떠케 쓰느냐? 잘 -_- 아닙니다.. 우선..
다이렉트 드로우에 객체들에 대해 알아보죠..
① idirectdraw7 : 다이렉트 드로우 객체로 머.. 굳이 회화에 비유하자면
도구 통이라고 생각하시면 될거십니다!
② idirectdrawsurface7 : 한마디로말해서 말그대로 표면입니다.. 비됴메모리나
시스템메모리에 할당되는 이미지정보를 담은 포인터
라고 생각하시면 됩니다.. 이것도 회화에 비유하자면
바로! 도화지 입죠..
.
③ tddsurfacedesc2 : 말그대로 표면의 정보를 담고있는 클레스입니다.
회화에 비유하자면 애매해서리.. 머라고 해야하낭
도화지를.. 자기 용도에 맞게 준비하는거라고
해야할겁니다
우선 대충 이정도로 클레스 설명을 끝내죠.. 나머지는 점차 알아나가도락 하죠
자 그러면 본격적인 초기화 설명에 들어가기로 하죠.. 우선 새로운 기분으로
new application을 눌러줍니다. 그리고 새로운 폼이 뜨션나요?
그러면.. 낼름.. 유닛 코드로 들어가셔서 interface 아래 uses부분에 directdraw
를 추가시킵니다.. 인제 그럼 준비는 다된네여.. 우선.. 폼의 public부분에
다이렉트드로우 변수명 : idirectdraw7;를 추가시켜 주세요..
전 ddraw7로 할랍니다..
추가 시켜 주션나요? 그러면.. 인제 힘차게 폼크리에이트 이벤트를 열어주세요
그런다음 아래코드를 입력합니다
color := clblack; {폼의 색상을 검은색으로)
borderstyle := bsnone;{폼의 가장자리 제거}
cursor := crnone;{폼에서 커서를 없엔다)
자 그러면.. 그담엔 다이렉트 드로우 객체를 생성해야 되겠지요?
(640*480 16비트 모드의 풀스크린을 만드는겁니다);
if directdrawcreateex(nil,ddraw7,idirectdraw7,nil) <> dd_ok then
raise exception.create('directdraw 객체 생성 실패');
if not assigned(ddraw7) then exit;
{만약 ddraw7이 할당이 안됐으면 나간다}
if ddraw7.setcooperativelevel(form1.handle,ddscl_exclusive or
ddscl_fullscreen or ddscl_allowreboot) <> dd_ok then
raise exception.create('배타적 풀스크린 얻기 실패');
{ 전체화면 모드로 변환한다}
if ddraw7.setdisplaymode(640,480,16,0,0) <> dd_ok then
raise exception.create('640 x 480 16bit 모드 실패');
{화면모드를 640 * 480 16비트 모드로설정한다}
자 되되었습니다.. 이러면 그냥 화면이 가맣게 되면서. 그냥 -_-나옵니다.
(나오실라면 알트 f4 도 괜차는데 keydown이벤트에 그냥 close하나 만들어주세여)
이젠 초기화 함수설명을 해야죠.. 우선
directdrawcreateex(nil, directdraw 객체 변수명,idirectdraw7 ,nil)
에 대해 알아보겠습니다..
우선이것은.. 말그대로 다이렉트 드로우 객체를 생성하는겁니다..
앞뒤에 nil은 저도 모르지만 그냥 nil이랍니다.. 그리고 가운데 directdraw객체명은idirectdraw7 변수형을 가지는 변수명을 써주세요...
ddraw7.setcooperativelevel(폼의 헨들,ddscl_exclusive or ddscl_fullscreen or
ddscl_allowreboot);
이함수는 화면 모드를 설정한는 부분인데요 굳이 설명할필요는 없고..
그냥 전체화면 만드는 함수라고 생각하시면 됩니다.
(나중에 제가 플레그 레퍼런스를 적어서.. 올리죠..) 그럼 다음함수
ddraw7.setdisplaymode(가로크기,세로크기,모드,0,0) 이함수는
화면 디스플레이 모드를 설정하는 함수인데요.. 모드부분엔
16비트면 16 256칼라면 8 24비트면 24 라고 입력하면됩니다.
2.정리~~
우선 인제 초기화는 했으니.. 해제법을 알아야 겠지요?
폼 디스트로이 이벤트창을 힘차게 여세여 그런다음 아래코드를
넣어주세여~~
if assigned(ddraw7) then ddraw7._release;{만약 할당ㄷ으면 풀어쇼!)
pointer(ddraw7):=nil; {닐로 정리쇼}
이러면.. ddraw7객체를 해제 합니다..
3.최종 소스코드;
procedure tform1.formcreate(sender: tobject);
begin
color := clblack;
borderstyle := bsnone;
cursor := crnone;
if directdrawcreateex(nil,ddraw7,idirectdraw7,nil) <> dd_ok then
raise exception.create('directdraw 객체 생성 실패');
if not assigned(ddraw7) then exit;
if ddraw7.setcooperativelevel(form1.handle,ddscl_exclusive or
ddscl_fullscreen or ddscl_allowreboot) <> dd_ok then
raise exception.create('배타적 풀스크린 얻기 실패');
if ddraw7.setdisplaymode(640,480,16,0,0) <> dd_ok then
raise exception.create('640 x 480 16bit 모드 실패');
end;
procedure tform1.formdestroy(sender: tobject);
begin
if assigned(ddraw7) then
begin
ddraw7._release;//해제한다
pointer(ddraw7):=nil; //포인터로 타입캐스팅한후 nil을 대입해 제거한다
end;
end;
procedure tform1.formkeydown(sender: tobject; var key: word;
shift: tshiftstate);
begin
if key=vk_escape then close;
end;
-------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[319] 제 목 : [강좌] dx강좌-1(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 15:50:40 읽음 : 59 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
자 드디어 기다리고 기다리셔떤! 다음강좌(너무늦엇죠? -_- 그동안 게임에정신이
팔려서 퍽! 헉.. 그렇다고 돌을 던지시다니 너무해 t.t 흘흘흘.. 그러면 요번강좌
전체적 설명을 드리죠 요번강좌는. 바로.. 아싸가자비! 도화지를 펼쳐보자
입니다.. 차분히 말하자면.. 그냥.. 더블버퍼링 표면생성이죠... 그라면... 시작허것씁
-----------------------------------------------------------------------
*(특강)*
...더블 버퍼링이란 무엇인가!
일반적으로 화면에 무엇을 그려준다고 생각해볼 때.. 만약 그려주는 장면을.. 보여준다
게임이 정상적으로 진행되지안고 깜빡임 현상이 나타나게된다. 그래서 이러한 문제를
해결하기위해 하나의 버퍼를 잡아놓고 그곳에서 모든 이미지처리를 해준다음
전면으로 고속 전송을 해주는 것이 바로 더블 버퍼링인 것이다!
1.드로우 서페이스의 생성...
저번강좌애서 다이렉트 드로우에대한 기초적 설명을 이해하신분들은 이미 알고있듯이
한마디로 그림정보를 가지고 있는 포인터입니다. 그러면 이눔의 것을 어떻게 만드느냐?
잘 -_- (퍽! 돌은 제발 던져주지마세여 아파여!) 제가 쓸 강좌는 기초적으로. 더블
버퍼링을 기초로 합니다. 그럼 저번 소스있죠? 거기 의 폼클레스의 퍼블릭에
아래 변수를 추가합니다..
primarysurface,backbuffer : idirectdrawsurface7; {<- 전면버퍼와 후면버퍼}
그리고 저번소스의 폼크리에이트 부분에 지역변수로
ddsurfacedesc : tddsurfacedesc2; {표면 디스크립션}
ddscaps : tddscaps2; {표면 정보}
자그럼 준비는 다된네여.. 자. 그러면.. 저번에 초기화 부분의 바로 뒤에서부터
시작을하는 겁니다.. 저번에 다이렉트드로우7객체 변수명이 ddraw7엿죠?
그럼 우선 아래코드를 보세여~~~~
begin
{지난번초기화 바로아래}
fillchar(ddsurfacedesc,sizeof(tddsurfacedesc2),0); {디스크립션 초기화}
with ddsurfacedesc do
begin
dwsize := sizeof(tddsurfacedesc2); {사이즈결정}
dwflags := ddsd_caps or ddsd_backbuffercount; {서페이스 속성}
ddscaps.dwcaps := ddscaps_complex or ddscaps_flip or
ddscaps_primarysurface; {서페이스 정보}
dwbackbuffercount := 1; {더블버퍼링이니 백버퍼카운터는 1}
end;
if ddraw7.createsurface(ddsurfacedesc,primarysurface,nil) <> dd_ok then
raise exception.create('복합화상공간 생성 실패'); {전면버퍼생성}
fillchar(ddscaps,sizeof(ddscaps),0); ddscaps.dwcaps := ddscaps_backbuffer;{표면정보를 벡버퍼로}
if primarysurface.getattachedsurface(ddscaps,backbuffer) <> dd_ok then
raise exception.create('후면 버퍼 생성 실패');
{백버퍼를 전면버퍼에 부착생성}
end;
자.. 다 코딩 하션는지요.. 그러면 전체적인 설명에 들어가도록 하겠습니다..
*fillchar(ddsurfacedesc,sizeof(디스크립션 변수명),0);
-머 아시다시피 0으로 채워주는겁니다..
* dwsize := sizeof(디스크립션 변수명);
-디스크립션의 크기를 정하는 과정입니다.
*dwflags := 플레그들;
-화면의 속성들을 설정한는 것입니다..
* ddscaps.dwcaps := ddscaps_complex or ddscaps_flip or
ddscaps_primarysurface;
-화면 정보를 담고있습니다 예를들어 위는 복합적인 플립이되는 전면버퍼입니다
**플립이란? :백버퍼를 전면버퍼로 전송하는게아닌 주소 뒤바뀜으로 빠른 화면출력
이 가능하게되는 기술입니다;
*dwbackbuffercount := 1;
-백버퍼의 개수를 정합니다..
*ddraw7.createsurface(디스크립션 변수명,서페이스 변수명,nil)
-머 이름에서 풍기다시피 서페이스를 생성하는 함수인데 생성할 때
디스크립션 변수를 참조해서 그에 해당하는 표면을 생성합니다.
*전면버퍼변수명.getattachedsurface(켑스변수명,후면버퍼변수명);
-이 함수도 한마디로 후면버퍼를 생성해서 전면버퍼에 붙여주는 겁니다.
2.정리
인제 생성을 해주었으면 결자해지 라고... 해제를 해주어야게찌요?
그러면 저번소스에 폼디스트로이 부분에 아래코드를 대려줍시다..
{저번 디스트로이 이벤트 바로아래!)
if assigned(primarysurface) then primarysurface._release;
pointer(primarysurface):=nil;
{보시면 아시게찌만 만약 전면버퍼가 할당되어이쓰면 해제한다.. 이런뜻입니다}
3.전체코드 정리
*.. 주의 여기서 주석처리는 저번소스와의 해깔림방지용이므로.. 잘읽어보시길...
{전강좌 퍼블릭에 서페이스변수 추가}
public
//전강좌 변수들이 존재
primarysurface,backbuffer : idirectdrawsurface7;
{전강좌 소스에 폼크리에이트에 추가로 지역변수2개 추가 및 코딩}
var
//전강좌변수들
ddsurfacedesc : tddsurfacedesc2;
ddscaps : tddscaps2;
begin
//전강좌 코딩들!
fillchar(ddsurfacedesc,sizeof(tddsurfacedesc2),0); {디스크립션 초기화}
with ddsurfacedesc do begin
dwsize := sizeof(tddsurfacedesc2); {사이즈결정}
dwflags := ddsd_caps or ddsd_backbuffercount; {서페이스 속성}
ddscaps.dwcaps := ddscaps_complex or ddscaps_flip or
ddscaps_primarysurface; {서페이스 정보}
dwbackbuffercount := 1; {더블버퍼링이니 백버퍼카운터는 1}
end;
if ddraw7.createsurface(ddsurfacedesc,primarysurface,nil) <> dd_ok then
raise exception.create('복합화상공간 생성 실패'); {전면버퍼생성}
fillchar(ddscaps,sizeof(ddscaps),0);
ddscaps.dwcaps := ddscaps_backbuffer;{표면정보를 벡버퍼로}
if primarysurface.getattachedsurface(ddscaps,backbuffer) <> dd_ok then
raise exception.create('후면 버퍼 생성 실패');{백버퍼를 전면버퍼에 부착생성}
end;
{전강좌의 폼디스트로이이벤트에 코딩추가!}
if assigned(backbuffer) then
begin
backbuffer._release;
pointer(backbuffer):=nil;
end;
if assigned(primarysurface) then
begin
primarysurface._release;
pointer(primarysurface):=nil;
end;
if assigned(ddraw7) then
begin
ddraw7._release;//해제한다
pointer(ddraw7):=nil; //포인터로 타입캐스팅한후 nil을 대입해 제거한다
end;
-----------------------------------------------------------------------
에구.. 이번에도 너무 성의 없이 쓴거가타서 씁쓸하네여.. 해보시고 안되는
부분이있으면.. 질문해주세여.. 제발.. -_- 누가 질문이래도 해야지 -_- 힘나서
쓰죠..ㅠ.ㅠ 그러면 다음강좌는 점찍기 밎 화면전송을 알아보도록하죠...
이부분이 아주중요한데요.. 예외핸들러 및 화면복구함수 그리고 화면플립합수의
사용등 아주 중요한 부분이 다루어 질거십니다..
----------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[320] 제 목 : [강좌] dx강좌-2(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 15:51:14 읽음 : 38 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
크하하하 드디어 돌아왔습니다.. -_- 엄청난공백을 깨고.. 초절정 하수의 dx강좌가
다시 이어집니다 (옆에있던 어떤분: 구차나서 강좌 안쓴주제에 말이많다! 퍼퍼벅)
그러타고 -_- 때리시다니 너무해 ㅠ.ㅠ! 강좌 계속할께요
------------------------------------------------------------------------
산뜻하게 시작해봐야 할텐데요 죄송하게도 요번강좌는 점찍기만 소개됩니다
왜냐하면 내마음이지!~~~ (
참점찍기 잘알아둬야함 왜냐? 내마음이지~ 퍼벅 흑
아니고용 바로 -_- 특수효과의 초강력 기초이기 때문입니다)
1. 점찍기
크핫핫핫 점찍긴데엽 .. 요놈은 어케하는것이냐? 우선 화면에 멀표시할라면
해당화면에 좌표에 해당하는 주소를 얻어와야 되는 것은 상식(상식 아니얌마! 퍼버벅)
헉 그런가요 -_- 아니면 말고요.. 우선 주소를 얻어오기전에 그 그 화면버퍼를
고정시키는 작업이 필요합니다 그게 바로 lock 이라는거죠 그리고 점을찍어줍니다
그런다음 고정해준걸 풀어줘야 안얼어죽죠? 요즘가치 추운날 하루종일 묶어두면
죽을겁니다. 그 풀어주는 것이바로 unlock입니다. 그럼 같이 점찍기 함수한판
만들어 보실랍니까?
자 우선 함수를 선언해야하는데 어디다가 선언을 할까요? 그건 여러분 마음이지만
폼의 퍼블릭에 꾸겨 넣겠습니다..
public
{지난강좌 코드들}
procedure putpixel(var buffer : idirectdrawsurface7; x,y : integer;
colors : word);
자 그럼 이함수의 선언이 되었습니다 아 저함수가 어드런 구조로 선언이
되언냐고요? 바로 맨처음 인자인 buffer 라는 서페이스에 x,y 좌표에 점을찍으라
는 겁니다.자그럼 코딩을 해야게쪼?
procedure form1.putpixel(var buffer : idirectdrawsurface7; x,y : integer
;colors : word);
var
lpdesc : tddsurfacedesc2; {이눔은 바로 화면정보를 얻어올 눔임..)
begin
fillchar(lpdesc,sizeof(tddsurfacedesc2),0); //0으로 채워줍니다
lpdesc.dwsize := sizeof(tddsurfacedesc2); //사이즈를 정해주죠?
repeat
until buffer.lock(nil,lpdesc,ddlock_surfacememoryptr +ddlock_wait, 0)=dd_ok;
//화면 정보를 얻어냅니다 얼린다고나할까?
pword(dword(lpdesc.lpsurface)+lpdesc.lpitch*y+x*2)^ := word(colors);
//화면 (x,y) 좌표에 점을 똬악 찍어삐!
buffer.unlock(lpdesc.lpsurface); //화면 풀어주기
end;
자.. 저 코드중 중요한 것은 바로 점찍는부분.. 그부분에 대한 설명을 아래에 쓰거씀니당
*lpsurface : 이게바로 버퍼의 시작번지입니다..
*lpitch : 이건 화면의 논리적 가로크기입니다.
그럼 위에 이상한 조합식은 머신가? 바로 x y 에해당하는 좌표 번지를 받아서
컬러값 즉 지금은 16비트니 $0~$ffff 까지의 색상수중 하나를 대입하면되는
겁니다..자그럼 점을찍어보실까요 우선 아직은 메시지헨들러가 없으므로
그냥 시작할 때 프라이머리에 점한번 찍는걸로 마무리하죠.. 그럼 폼쇼이벤트를
열고!
procedure form1.formshow(sender : tobject);
begin
putpixel(primarysurface,2,2,$001f); {전면버퍼의 2,2에 파란색 점을 찍는당!)
end;
2. 당부의 말씀
만약위에 코드가 에러가난다면 점찍기부분을 초기화 맨뒤에 놔두시면되겠습니다.
그리고 지금까지 강좌를 보아 오시면서 만든소스는 계속 저장해두십시오
계속 추가된느 식으로 나갑니다..
-------------------------------------------------------------------------
다음강좌에 다시만나용~~
------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[321] 제 목 : [강좌] dx강좌-3(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 15:51:41 읽음 : 35 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
ㅠ.ㅠ 저도 고통의 나날이 였습니다 양해 해주세엽~~ 드디어 돌아온 신동훈의
엉성 dx 강좌 그 4번째시간! 쿠궁 기대되시져? 으흐흐 바로 메시지 헨들러와
flippingenabled 프로퍼티를 맹글어보는 시간입니데잉~~~~
오늘은 시작전에 예전 강좌에써먹던 노래를 한번 불르고 시작하죠......
꺼야꺼야 강좌할거야 혼자서도 강좌할꺼야 ~~~ 짠짠
헉 ㅠ.ㅠ 그러타고 돌을 날리시다니
너무해 ㅠ.ㅠ 퍼억 (지나가던 꼬마사과님 : -_- 강좌나 잘해! -_- 둬허헉 )
(추신:꼬마사과님 -_- 이건 개그입니다ㅠ.ㅠ(증인목소리로) 미안합니다 웃기려고 하다보니)
------------------------------------------------------------------------
자 이젠 화면에 멀 그려봐야 할듯한 역사적 사명이 느껴지지 않습니까?
그렇습니다 우리는 화면에 머라도 그려내야하는 막중한 임무를 띠고 델파이에
입문한겁입니다. 이것에도 방법이 여러 가지 있는데 도스시절엔 무한루프를
돌리는 방법으로 이것을 주로 했다던데 잘은 모르겠구 요즘은 대부분.
메시지헨들러를 맹글어서 쉬는 시간동안 컴퓨터를 혹사시키는 즉 idle 타임에
그려뿐지기를 합니다. 그럼 우선 이것을 맹글어햐할텐데여.. 우선 예전강좌에
따라 하셨던소스가 있으실텐데.. 그걸 우선 열어보세여... 그리고 폼 프라이베이트에
procedure handlemessage (var msg : tmsg; var handled : boolean);
procedure idlehandler (sender : tobject; var done : boolean);
위에 두 개의 프로시져를 우선 등록합니다.. 그리고 그림을 그릴 프로시져인
procedure updatedisplay(is_commandable : boolean);를 폼퍼블릭 에 넣습니다
인제 우선은 모든 것이 다장만이 돼씁니다....... 이제 아래코드들은 보실까여?
procedure tform1.handlemessage(var msg : tmsg; var handled : boolean);
begin
updatedisplay(true); // 화면을 갱신하는걸 허락한다
end;
procedure tform1.idlehandler(sender : tobject; var done : boolean);
begin
updatedisplay(true); // 미투~~~~
done := false;
end;
procedure tform1.updatedisplay(is_commandable : boolean);
begin
//나중에 소스가 들어감.
end;
우선 코드는 완성된네여 자 이 코드들의 뜻은 주인님의 허락이
떨여 져쓸땐 우리는 무대뽀로 화면을 그려야한다라는 대강적 뜻을 포함하고
있습니다. 근데 이러케만 코딩을 하면 과연 이게 돌아갈까여 결론은
절때로 안돌아간다는 것이죠.. 그러면 이걸 어떠케 해야 돌아가게
만들까여? 결론은 application 객체에 이벤트를 등록해야하는 것이죠...
그런데 그러면 상태를 바꿀때마다 handlemessage 와 idlehandler를
등록해줘따 안해줘따 해야하는가. 이건 쫌 불편하죠.. 그러면 한순간
쫌 긴코딩을 하더라도(길지도 않습니다만) 화면갱신 여부를 단한줄로 조정할쑤
있는 방법이있습니다 바로 프로퍼티를 붙이는거죠.. 그럼 프로퍼티를 붙여볼까요?
우선 내부적으로 쓰일 변수와 함수를 프라이베이트 넣습니다.
fflippingenabled : boolean;
procedure setflippingenabled(value : boolean);
외부에서 건들면 안되는것이니깐요.. 헤헤 그러면 프로퍼티는 어디서든지
제어가 가능해야 하니깐 바로 폼퍼블릭에다가 넣어야 합니다.
property flippingenabled : boolean read fflippingenabled
write setflippingenabled;
이런 식으로요 그러면 인제 실제 코딩을 해야되겠죠?
procedure tform1.setflippingenabled(value : boolean);
begin
if value <> fflippingenabled then begin
fflippingenabled := value;
if fflippingenabled then begin
{ 사용자 이벤트 핸들러 설치 }
application.onmessage := handlemessage;
application.onidle := idlehandler;
end else begin
{ 사용자 이벤트 핸들러 해제 }
application.onmessage := nil;
application.onidle := nil;
end;
end;
end;
자 이제 다됐습니다. 위의 프로시져를 통해 flippingenabled 프로퍼티가 제어가 됩니다.
만약 여러분이 소스의 어느곳에 서라도 flippingenabled:=false; 를하면 프로그램은
화면갱신을 안할것이고 어디서든지 flippingenabled:=true 를하면 프로그램은
화면갱신을 해내고야 말것입니다..
-------------------------------------------------------------------------
아참 directx7.0 헤더로 초기화를 해보니 참으로 쉽더군요 그방법은 차후에 올리든지
아니면 제가 자료실에 이때까지의 소스를 올려놓지요....
아참 이강좌뒤에 바로 또 4탄강좌 나가는데요 그거 꼭보셔야합니다 지금은 단지
까만화면만 출력될뿐이지만... 다음강좌엔 makeitso라는 서페이스갱신 판별 함수가
나옵니다 그걸 이요해서 flip 이라는것과 blt 같은것들은 해보기로 하죠..
-----------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[322] 제 목 : [강좌] dx강좌-4(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 15:52:22 읽음 : 37 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
이제 올린김에 왕창올리져! 전번강좌에서 약속한 대로 전번에 맹글어놓은
갱신프로퍼티인 flippingenabled를 사용해서 화면에 점이라도 찍는걸 하도록하죠
그걸 위해서 makeitso 라는 에러 여부판단 함수를 만들게씁니다
------------------------------------------------------------------------
자 여러분 강좌가 이상한걸 못느끼셨습닉까? 예 그렇습니다 번호표 메기는게 -_-
없어져찌요.. 그만큼 강좌가 짤븐 이유도 있겠습니다만 -_- 제 게으름 때문입니다.
설명이 쫌 부실할쑤도있는데 점찍기나 다른 중요한 부분에 있어서는 설명을
잘할것입니다. 그러면 makeotso라는 정체불명의 함수를 맹글어야 할텐데..
그럼 아래놈을 폼퍼블릭에 넣어 보세여 우선..
function makeitso (ddresult : hresult) : boolean;
이함수의 용도는 위에도 말씀드려찌만. 바로 에러여부 판단 함수이고
만약 에러가나따면 이눔은 false를 반환할것이고
성공했다면 true를 반환하게찌요... 그럼 우선 아래코드를 보세여...
function tform1.makeitso(ddresult : hresult) : boolean;
begin
case ddresult of
dd_ok : result := true;
// dderr_surfacelost : result := restoresurfaces <> dd_ok; 주석처리
else result := ddresult <> dderr_wasstilldrawing;
end;
end;
흠 상당히 적지않게 이상하다 생각하신 분들이 계실텐데여.. 저위에 플레그들의
의미는 dd_ok는 제생각엔 directdraw_ok란 것 의 축약형인것
같은데요 저반환값이 directdraw의 함수들이 성공했다는 반환값인것입니다
나머지들은 먼가 문제가 있다는것이지요 (우선 이렇게 알아두세여)
그럼 인제 소스를 다맹글었으니. 으흐흐흐흐.. 화면갱신을 해볼까여?
우선 화면 갱신을 해보기전에 다음 ddraw 함수들에대한 설명이 들어갑니다.
우선 blt 라는 함수를 설명하기로 하죠 자 델파이에서 서페이스명. 예를들어
우리가 저번에 만든 bakbuffer. 이라고 치면 아래 서페이스 객체의 여러 가지
함수들 변수들이 나오는데 그중 딱 보이는 것 blt 와 bltfast라는 함수가 보입니다
우선 기능을 설명드리자면 api의 bitblt와 그기능이 흡사합니다. 바로 화면에
먼가를 그리는것이지요 그러나 blt 라는 함수는 목표서페이스의 그릴영역과
그려질 즉 소스서페이스의 영역을 둘다 지정할쑤 있고 bltfast는 무조건
소스 서페이스에 사용자정의 영역을을 사용자정의인 x y 좌표에 맞춰 그려지지요..
그러니깐 blt는 그릴영역과 그려질 영역을 둘다 지정할쑤있고
bltfast는 그릴 영역만 지정할쑤 있죠 이해가 가시나요? 안가시면 -_-
저에게 메을을 보내주세여.......... 헤헤헤..
자그럼 또다른 화면갱신 함수인 flip 에관해 알아 보겠습니다..
이것은 주로 벡버퍼에서 전면버퍼로의 고속 화면 전송에 이용되는 함수입니다.
즉 말하자면 후면버퍼를 달고있는 서페이스만이 가능하단 이야기죠..
예전 초기화강좌를 보면 backbuffer는 특이하게
primarysurface.getattachedsurface(ddscaps, backbuffer); 라고 코딩했던 기억이날껍니다.
(안나시면곤란 -_-) 말그대로 벡버퍼를 전면버퍼에 붙여버린거죠 이렇게
해놔야지만 flip 이가능 하게됩니다.이 flip 이란 이론은 간단하게 설명 드리자면.
도화지 두장이 있습니다 이것두개를 겹치게 붙이고 뒤에다가 그림을 그립니다.
그런다음 뒤집어서 뒷면을 보여주는사이 또다른 뒷면이된 예전 앞면에
그림을그리고 뒤집은다음 그림을 그림고 또 뒤집고 하는 이런식으로 컴퓨터이론
적으로 설명드리자면 두 버퍼의 주소를 바꺼서 실제적 전송이 없이 보여주는것이죠이러케함으로써 전송에 드는 시간을 줄일수 있죠. 상당히 복잡하게 보입니다만..
그냥 이러쿠나 라고 알아두싶쇼 참고로 flip은 전체화면 모드에서만 가능합니다...
에고... 설명이 길었는데 그러면 각함수의 인자들을 알아보죠..
우선 blt
그릴서페이스.blt(그릴영역(prect형임), 그려질 서페이스 , 그려질 영역(prect형임),플레그,nil);
그리고 bltfast
그릴서페이스.bltfast(그릴 x 좌표 , 그릴 y 좌표 , 그려질 서페이스 , 그려질 영역,플레그);
마지막으로 flip
primarysurface.flip(nil,ddflip_wait);
(이것의 인자들은 보통 이렇게 쓰는게많으므로. 우선 이렇게 적어 두세여..)
에고.. 허리야.. 인제 화면좀 갱신해봅세다...........
전번에 맹글어놓은 updatedisplay 함수안에 코딩을 해야합니다....
우선 렌덤하게 화면에 점찍는거부터 해보죠
procedure tform1.updatedisplay(is_commandable : boolean);
begin
putpixel(backbuffer,random(640),random(480),$1f);
//기억나시죠? 전번에 맹그어떤함수
repeat
until makeitso(primarysurface.flip(nil,ddflip_wait));
end;
자 이함수는 아싸가자비! 렌덤하게 점찍깁니다 -_- 자 그러면 인제 컴파일하고
실행시켜보세여.. 으흐흐-- 아마 화면이 까마키만 할뿐일껍니다.. 지금 저에게
속으신분들은 바로 지난 3편강좌를 안보신 분이거나 대충보신 분일껍니다.
우리는 폼으로 flippingenabled 함수를 만든게 아닙니다. 이걸 true로 놔주셔야죠.
자 폼쇼이벤트를오랜만에 다시여시고! 맨마지막줄에.
flippingenabled:=true;를 넣어주세여 -_- 화면에 화려하게 찍히는 퍼러색 점을
볼쑤있으실겁니다.........
------------------------------------------------------------------------
으흐흐 다음번 강좌에는 본격적인 blt 와 bltfast 활용을알아보기로 하죠..
-----------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[323] 제 목 : [강좌] dx강좌-5(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 15:52:40 읽음 : 41 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
이제부터는 ...서페이스에 bmp로딩하기 와 화면에 출력하기를 해보게씁니다...
흠 그리고 오프스크린을 만드는 작업도 하게쓰니 부디ddutil.pas라고 제가 자료
실에 올려놓은것을 꼭받아 주시기 바랍니다
---------------------------------------------------------------------------
참 오랜만이네여... 흠.. 아래 강좌들은 지난강좌 정리해서 재탕한거고요..
이번부터가진짭니다.. 흠 강좌가 순서가 뒤죽박죽이여서리.. 흠 지금까지
한가지소스로 해오셔따면 소스가 인제 화면에 렌덤하게 점을팍팍찍는게
나오겐네여 인제 점은 싫다.! 하시는분덜.. 그림한번 찍어봅세다...
우선 bmp 그림 아무거나 준비하십시요 흠 그럼 가볼까여?
자.. 우선프로그램이 실행되는 디렉토리를 알아내야게쪄? bmp가 어딘는줄알고
헤맵니까.. 흠 전역변수로 selfdi
r: string;을 선언합세다~~~
선언핸나여? 그러면 폼크리에이트에 아래코드를 추가하세여..
selfdir:=extractfilepath(application.exename);
이렇게하면? 지금 실행되고있는 디렉토리를 알게되게져 흠. 그러 본론으로들어가서
우선 그림을 로딩해야게쪄? bmp를 하나 준비하세요 물론 소스저장한 폴더에다가
꾸겨넣어야죠..(전 mybmp.bmp 로할랍니다);
그런다음 또한 전역변수로 idirectdrawsurface7 을하나 선언하죠 이렇게
image : idirectdrawsurface7;
흠 인제 저 image란 서페이스에 bmp를 로딩해야겐는데 떠헉 timage처럼 로드프롬
파일이 없당! 어카지 우!!!!! 그러나 걱정마시라... 이럴때를 대비해 ddutil이란
놈이있었으니... 후후후 자 아래코드를 보세용...
//지난 초기화 부분 맨아래
image:=ddloadbitmap(ddraw7,selfdir+'mybmp.bmp',0,0);
자이러면 image에 비트멥을 로딩하는겁니다 간단하죠? 흠 ddloadbitmap이란함수는
idirectdrawsurface7 을반환하는데 이것은 result인 idirectdrawsurface7를
생성하고 비트멥을 로딩하는 함수입니다. 자그러면 비트멥 로딩도 끈나쓰니...
본격적으로 그림을 그려야겐는데... 흠 어디다 그릴까! 어이 이봐들 강좌안봔나?
updatedisplay 이짜너.. 참으로.. 지난번 putpixel 함수를 넣었는데 이것을지우고
서페이스를 그리는 함수를 넣어야 그림이 짠 하고 나타나겐네여....
자그럼 아래소스를 보시죠
procedure tform1.updatedisplay(is_commandable : boolean);
begin
repeat
until makeitso(backbuffer.bltfast(0,0,image,nil,ddbltfast_nocolorkey));
//백버퍼에 image서페이스를 전송하ㅗ
repeat
until makeitso(primarysurface.flip(nil,ddflip_wait));
//전면버퍼에 백버퍼를 고속전송한다
end;
자 위에 지난강좌에서 언급하여떤 bltfast가나오는데 우선 함수부터 살펴보죠
*****(bltfast는 서페이스 객체가 가지고잇는 전송함수입니다.)
목표서페이스.bltfast(목표 x좌표,목표 y좌표, 소스서페이스 ,소스렉트(prect형),플레그);
자위에 소스에서보면 벡버퍼에 0,0에 image서페이스를 엥 prect인데 nil?
더헉이라고 생각하시는분 있는데 nil을치게되면 알아서 사이즈를구해서
보내므로 괜찮습니다 굳이 rect쓰시게따 하시면 drawrect:trect; 이렇게
잡으셔서 렉트 설정해주시고
backbuffer.bltfast(0,0,image,@drawrect,ddbltfast_nocolorkey);
요로코롬 하시면됩니다. 자그리고 중요한건 그뒤 플레그 부분입니다...
ddbltfast_nocolorkey라고 핸는데 이 컬러키라는넘이 머길레 안한다고 날리인지
알아보까여? 컬러키라함은 스프라이트처리를 필요로할때 쓰는겁니다...
지금은 단순히 bmp를 출력하는것이므로 스프라이트처리를 안한다고한거고요
헉 스프라이트처리가머냐고요 거참 공부좀해 공부! 공부해서 남주낭? 퍼억 ㅠ.ㅠ
(상국님 ㅠ.ㅠ 때리지마여) 퍼억(현철님 ㅠ.ㅠ 현철님마져) 퍼억 (기동님 떠헉
건방떨지말라니 ㅠ.ㅠ) 따악!(꾸에엑! 머프님? 엥 다아는데 왠건방이냐고요
ㅠ.ㅠ) 흑 그래도 설명하겠습니다. 스프라이트 처리란 흠 게임에서캐릭터는
캐릭터 모양만나오죠? 분명히 bmp는 사각형인데? 엥 그럼 캐릭터모양 bmp라도?
아니면 무슨 네모는싫어를응용한 패널이 떠다니는걸까요? 아닙니다 캐릭터부분을
제외한 나머지 부분은 한색으로(주로 검정색) 칠하고 그색은 찍어주지 않는겁니다
그렇게해서 캐릭터를 표현하는거지요!
(기본적으로 ddutil에선 검정색을 스프라이트 색으로 처리합니다 제가 그렇게 해놔써여)자그럼 스프라이트처리할라면? 뒤에 플레그만 바꿔주면 되게쪄?
ddbltfast_srccolorkey;로.. 바꺼주시면 됩니다. 기본저으로 bltfast함수는
그기능이 마치 bitblt와 동일합니다 이미지 확대축소가 안되고 그대로만..
전송이가능하죠 대신 빠릅니다. 그러면 이미지 확축은 어케하지? bltfast함수대신
blt라는 넘을쓰면 가능하져 그모양은?
drawrect:=rect(0,0,random(640),random(480));
backbuffer.blt(@drawrect,image,nil,ddbltfast_nocolorkey,nil);
이렇게 해서 위에 bltfast를 지우고 blt함수를 넣으면 렌덤하게 확축되서 나오게쪄
자 blt함수를 살펴볼까여?
목표서페이스.blt(찍을범위렉트,소스서페이스,소스렉트,플레그,이부분은 nil로쓰세여우선);
자 목표서페이스에 소스서페이스를 찍을범위에 소스렉트만큼 확대 또는 축소해서
그려준다는뜻입니다.. 역시 플레그부분엔 ddbltfast_nocolorkey가 들어간는데
위에 설명해쓰므로 스프라이트처리시 플레그만 설명하게씀니다...
스프라이트 처리시 blt는 ddblt_keysrc 라는 플레그를 쓰면됩니다. 이 blt는..
gdi함수중 stretchblt와 그기능이 같습니다.
자그럼 강좌를 정리하까여?(예제는 자료실에 올립니다)
////////////////////////////////////////////////////////////////////////////
var
image : idirectdrawsurface7; //전역변수로 image선언
//지난초기화부분
image:=ddloadbitmap(ddraw7,selfdir+'mybmp.bmp',0,0);
flippingenabled:=true;
end;
procedure tform1.updatedisplay(is_commandable : boolean);
begin
repeat
until makeitso(backbuffer.bltfast(0,0,image,nil,ddbltfast_nocolorkey));
//백버퍼에 image서페이스를 전송한다
repeat
until makeitso(primarysurface.flip(nil,ddflip_wait));
//전면버퍼에 백버퍼를 고속전송한다
end;
또는 blt를쓰는경우
procedure tform1.updatedisplay(is_commandable : boolean);
var
drawrect : trect;
begin
drawrect:=
rect(0,0,random(640),random(480));
repeat until makeitso(backbuffer.blt(@drawrect,image,nil,ddbltfast_nocolorkey,nil));
//백버퍼에 image서페이스를 렌덤하게 확축 전송한다
repeat
until makeitso(primarysurface.flip(nil,ddflip_wait));
//전면버퍼에 백버퍼를 고속전송한다
end;
// 폼 디스트로이 이벤트에 image서페이스 파괴하는걸만든다..
//방법은 backbuffer와 동일
///////////////////////////////////////////////////////////////////////////
그럼 다음강좌에서 보죠...
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[324] 제 목 : [강좌] dx강좌소스 자료실에 올립니다
올린이 : 신동훈(리이우롱) 등록시각:2000-11-13 16:00:40 읽음 : 38 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
받아서 보세여~~
------------------------------------------------------------------------------
------------------------------------------------------------------------------
『델파이 동호회-팁 (go delphif)』
[325] 제 목 : [강좌] dx강좌-6(up버젼)
올린이 : 신동훈(리이우롱) 등록시각:2000-11-23 20:44:07 읽음 : 47 받음 : 0
관련자료 없음
------------------------------------------------------------------------------
-------------------신동훈(초절정하수)의 엉성 dx좌!-------------------------
자... 금방올린다해찌만.... 그냥... 오랜만에 올려버립니다 퍼벅!
기동님 -_- ㅠ.ㅠ 절주기실 작정인가요? 퍼벅 헉 상국님 ㅠ.ㅠ
빡!!!!!!!!악! 현철님까지 ㅠ.ㅠ 푸우우욱 --; 머프님은... 사과깍던칼로?
떠헉 ㅠ.ㅠ 강좌는 누가 끈내오~~ 사람들에게 알리지 마시오 신동훈이
죽어따고 -_-; 따악! -_- ㅠ.ㅠ 알아써여 이번강좌는 예외처리입니다..
대충 보시져 흥 -- 따악 ㅠ.ㅠ 제발봐주세여 ㅠ.ㅠ (맨날때려 ㅠ.ㅠ)
-------------------------------------------------------------------------
자.. 저번강좌까지는.. 간단한 bmp로딩하는... 예제였습니다...
근데 이번강좌는.. 좀더나아간 예외처리부분에대해 하겠습니다...
어떤어떤 예외처리가 있을까요? 자풀스크린게임하다가 메세지가와서
밖으로나와따 -_- 이럴때 풀스크린이 미니마이즈가되죠? 이때 예외처리와
서페이스 분실시(-_- 진짜 드문일이지만) 이때 처리를 해야할것이고요
그럼 폼 프라이베이트에. 아래것들을.. 추가하세여
procedure exceptionhandler(sender : tobject; error : exception);
function restoresurfaces : hresult;
procedure drawsurface;
자추가해볼까여 맨처음 exceptionhandler는.. 에러처리를 위한것이고..
restoresurfaces는 화면 복구함수입니다.. 그리고 아래 drawsurface는
화면복구시쓰일 다시 서페이스에 그려주는 함수입니다..
그리고 전번강좌에 makeitso 부분에 서페이스 로스트시 리스토어하는
부분..의 주석들 풀어주세여... 그런다음 아래코드를 추가하세여
(이번강좌는 그냥 소스로 밀어 붙일랍니다 -_- 설명도 위에 한게거의다고)
procedure tform1.exceptionhandler(sender : tobject; error : exception);
var
wasenabled : boolean;
begin
{ 예외 메세지를 보이기 전에 gdi로 전환 }
messagebeep(0);
wasenabled := flippingenabled;
flippingenabled := false;
if assigned(ddraw7) then ddraw7.fliptogdisurface;
messagedlg(error.message,mterror,[mbok],0);
flippingenabled := wasenabled;
end;
function tform1.restoresurfaces : hresult; //리스토어 함수
begin
{ 화상을 잃었을때 makeitso에서 호출 }
result := primarysurface._restore;
if result = dd_ok then
begin
result := image._restore;
if result <> dd_ok then
begin
exit;
end;
end;
if result = dd_ok then drawsurface;//말마따나 다시그려주기
// end;
end;
procedure tform1.drawsurface;// 화면 다시그려주기
begin
//이안에 서페이스에 원래있던것들의 다시 로딩해주는것을
//넣으면됩니다.
end;
쩝 위에것이 다입니다 말그대로 -_- 예외처리한느것이므로.. 그안에 코드들은.
특히 drawsurface부분은... 임의대로 바꿔 사용하시기 바랍니다
그리고 또하나의 예외처리 미니마이즈와함께 저걸.. 폼의 이벤트에
연결시켜야합니다.. 고로 보기좋게 폼의 이벤트프로시져있는부근에
procedure formminimize (sender: tobject);
procedure formonrestore (sender: tobject);
위에것드을 추가하세여....~~~ 그리고 폼프라이베이트에
fpreviousflipping : boolean; 를추가하십쇼... (다쓸데가 있어!)
소스로 그냥또뿌립니다
procedure tform1.formminimize(sender: tobject);
begin
fpreviousflipping := flippingenabled;//지금 플리핑 여부를 저장한다
flippingenabled := false;// 플리핑을 멈춘다
end;
procedure tform1.formonrestore(sender: tobject);
begin
flippingenabled := fpreviousflipping;// 지난 플리핑여부를 검사해서 대입한다
windowstate := wsnormal;//폼을 정상으로 돌린다
end;
쩝 미니마이즈될대 멈처따가 다시 돌아올대.. 제대로 돌아오는함수입니다..
보시면 아시게쬬? 워낙간단한 소스라서리.. 쩝.. 그리고 마지막으로
간만에 오브젝트 인스펙터를 열고 폼페인트 이벤트를 여시고 다음코드를 추가하셉
if assigned(ddraw7) then
drawsurface;//서페이스다시 로딩 짠.. 하면 이제 예외처리는 끝입니다..
별로... 중요한부분도 아니니만큼 그냥 그렇구나 이해하시면됩니다
////////////////////////////////////////////////////////////////////////
흠.. 지금까지 해왔던것들은.. 템플리트화해서 딴데 저장해놓고.. 강좌새로
시작할때마다 복사해온다음 추가하는방식으로 하시면 편할껍니다.. 지금까지
해와떤.. 것들은.. 더나은것을 하기위한 기초중의 기초입니다... 흠 다음
강좌에선 dx의 색상체계및.. 점을찍는데에데한 지난번에 넘어간... 이론적
배경 그리고 간단한 이미지변환같은것들을 해보겠습니다.. 그런다음
반투명 및 여러가지.. 특수효가에 들어가지요..
이번소스도 올립니다. 전번에 풀었던 폴더에 덮어쓰세요..dx6이라는 폴더이름으로되있을껍니다 안되있으면 알아서 정리하십쇼퍼벅 ㅠ.ㅠ 정리해주세용 ㅠ.ㅠ
///////////////////////////////////////////////////////////////////////