Develop a simple RPG game with Delphi DirectX
Referring to RPG (Role Play Game, Role Play Game), I am afraid that you are not familiar with you. From an ancient classic DOS version of "Xianjian Qi Chuan" to the new tide "Xuanyuan Sword" series, there is no more beautiful storyline, beautiful and man-made protagonist, pleasant context music, shocked every player's mind. In terms of RPG, you can't mention DirectX because most of the RPGs on the PC are developed in this winter and winter. As early as the "Xuanyuan Sword", I have thought of using DirectX to write a self-rpg, to arrange the development of the storyline, but always because of this or that, there is no Can achieve this wish. After spending a valuable number of youth, I have done the triviality such as exam, love, abroad, and I can finally be able to share with my entire college career, listen to the decadence and sound exhaustion. Unknown songs, write some things that I have not written but I haven't written. Directx Introduction DirectX is not strange for most game enthusiasts (of course, those friends who only fight against DOS), before installing a game, the system will always prompt you to upgrade DirectX at the same time. Simply, DirectX is a series of DLLs, through these DLLs, developers can access the underlying hardware without device differences. DirectX encapsulates some COM (Component Object Model) objects, which provide a major interface for access system hardware. First, let's take a look at the structure of DirectX: [Related Map] Figure 1: DirectX Basic Structure DirectX is currently consisting of the following seven major parts: DirectDraw - Provide interfaces to programs directly access the memory, while keeping with other Windows applications compatible. Direct3D - provides an interface for accessing a 3D acceleration device. DirectInput - provides interfaces for various input devices, such as mice, keyboard, force feedback game handles and joysticks, and the like. Directplay - Provides a network function interface for the game, such as supporting data transmission in the game via protocols such as TCP / I, IPX. DirectSound - Provides direct playback of files such as WAV, MIDI to the accessed voice card. DirectSound3D - Through this interface, it can simulate the effect of a playback of a sound in any position in the three-dimensional space, thereby achieving realistic surrounding stereo. DirectMusic - This interface mainly generates a series of raw sound sampling feedback to the corresponding user event. Development Tool (Delphi & Delphix) Next, let's introduce the development tool. We usually install only only DirectX's run libraries (a series of packaged DLL files), the internal function structure is very complicated, so we also need DirectX development tools. The so-called workers must be good, and it must be aware of the tool. Although Microsoft announced DirectX SDK, because all headers are written in C / C , as the warm assistant of Delphi, we still have no way. Convert C / C code to PASCAL is not an easy thing, but don't worry, this work has been done. Japanese Hiroyuki Hori wrote a free component package for Delphi, called Delphix.
These components allow developers to easily access DirectX's DirectDraw, Direct3D, DirectSound, DirectInput (support feedback handles) and DirectPlay objects. The current Delphix package supports Borland Delphi 3/4/5/6/7 and DirectX 7.0 or higher (see Figure 2). After installed Delphix, we will not need to install Microsoft DirectX SDK. In this article we will use Delphix, you can download it from here. [Download] [Related map] TDXDraw DirectDraw and Direct3D assembly TDXDIB receiving the DIB (Device Independent Bitmap, Device Independent Bitmap) component TDXImageList picture list component TDX3D Direct3D component (used with TDXDraw) TDXSound DirectSound assembly TDXWave receiving Wave (Waveform Audio Files) TDXWAVELIST WAVE file list Components TDXINPUT Enter Components, including keyboards and handles Enter TDXPLAY communication components, used for online game development TDXSPRIEENGINE Elf Engine, used to manage the wizards generated in the game, see the game development process TDXTimer high speed timing The DIB version TDXPAINTBOX TPAINTBOX is more accurate than TTIMER, which is specifically used for game development animation principles before introducing the principle of the animation, let's introduce several DirectX terms. Surfaces here we are temporarily called surface. In DirectX, parts are used to store various bitmaps and video buffers in the memory are called surfaces. The surface currently displayed on the screen is referred to as a primary surface. During the experimental animation, we usually prepare to be at least one surface that is not displayed, referred to as a background surface (OFFSCREEN SURFACE). When you need to generate an animation, we can display the contents of the background surface to the screen directly, and turn the original main surface to the background without displaying. This way, it may be more likely to understand that we have played a small person in the book in a small time. Draw a small person in the lower space below the book, gradually change, and then quickly flip the whole book, you can see that some small people are jumping. Our current main surface is that you are now looking at that page, and the pages that have not been turned back later are the back surface, and the animation effect is achieved by rushing. When running some large games, the game will automatically call the system memory in the case of running out. At present, I want to run a DirectX game smoothly, and the non-3D class is more than 4M or more, and the 3D class is displayed, the better, the better. Frames Per Seconds usually refer to FPS, describe the examples we just mentioned, but also the number of books that we have turned over every second. When the number of frames reaches 24 frames per second, the human eye has not been distinguished, so that the picture is considered continuous. 24 frames used in the movie each second, while television uses 25 frames per second. In fact, there is a shot of two (12 frames per second) even a shot of three (8 frames per second) in Japan's animation production, and we can do not discuss it.
In the game, we will use a 24-frame or 25 frame per second to achieve the effect of deceiving the naked eye. Bitmaps and Sprites wizels refer to a set of pictures used to achieve animation effects in the game, which usually use a bitmap format and use a transparent area that is filled with specific colors. As shown below, it is a wizard. [Related Mapping] The black filling portion in the figure is a pre-defined transparent area. In the game, we can cut the entire picture in 9 pieces according to the white line, each with a size of 80 × 50. We first numbered from left to right and then numbered from top to bottom. If we are displayed by this nine pictures, and set the speed of the play to 24 sheets per second, we can get a spaceship in the rotating animation, that is, a spaceship elf. After the development process, after many nonsense, let's take off the paper on the paper and began formal development. In this example, we mainly implement the mouse to control the wizard to walk in eight directions. All pictures are from Daxu Company "Xuanyuan Sword", "The elf uses the image of Chen Jingge in the story. At the same time, please do not use these pictures for commercial purposes, otherwise the consequences are at your own risk. [Related Map] Background.BMP [related texture] Player.bmp Open Delphi and create a new application, select the TDXDRAW, TDXIMAGELIST, TDXINPUT, TDXIMAGELIST, TDXINPUT, TDXIMAGELIST, TDXINPUT, TDXIMAGELISTEENGINE components of the Delphix Components, and named DXDRAW, DXIMAGELIST, respectively , DXINPUT, DXTIMER, DXSPRITEENGINE, set its various properties as follows. For DXImageList, click on Items in Object Inspector, join two bitmaps (Background.bmp and Player.bmp), named Background and Player, set PLAYER's PATTERNHEIGHT and PATTERNWIDTH, set, set its transparentColor Pink (CLFUCHSIA). Control attribute value DXDraw Align alClient Display.Width 800 Display.Height 600 Display.BitCount 24 Options [doAllowReboot, doWaitVBlank, doCenter, doFlip] AutoInitialize True DXTimer Enabled True Interval 0 DXInput Mouse.BindInputState True Mouse.Enabled True DXSpriteEngine DXDraw DXDraw below is all The source program, first generate the corresponding event in Delphi and fill in the code, and finally press F9 to run the program. Click your destination with a mouse, Chen Jingyuan will automatically run to the designated place. Try to develop some simple games, use Delphix's cattle knife! All programs are tested in the Delphi 4.0 DirectX 8.0 environment. The controls required herein can be downloaded here.
Unit Main; Interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Menus, DXClass, DXSprite, DXInput, DXDraws; type TDirection = (DrUp, DrDown, DrLeft, DrRight, DrUpLeft, DrUpRight, DrDownLeft, DrDownRight); {self-direction is defined in the game are used} TPlayerSprite = class (TImageSprite) CanMove: Boolean; protected procedure DoMove (MoveCount: Integer); override; procedure MoveTo (MoveCount: Integer; direction: TDirection); procedure DoCollision (Sprite: TSprite; var Done: Boolean); override; end; TMainForm = class (TDXForm) {optimized TDXForm used herein instead TForm} DXTimer: TDXTimer; DXDraw: TDXDraw; DXSpriteEngine: TDXSpriteEngine; DXInput: TDXInput; ImageList : TDXImageList; procedure FormKeyDown (Sender: TObject; var Key: Word; Shift: TShiftState); procedure DXDrawFinalize (Sender: TObject); procedure DXDrawInitialize (Sender: TObject); procedure FormCreate (Sender: TObject); procedure DXTimerTimer (Sender: TObject Lagcount: integer; procedure DXDrawMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure DXDrawMouseMove (Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure DXDrawMouseUp (Sender: TObject; Button: TMouseButton ; Shift: TShiftState; X, Y: Integer); procedure FormClose (Sender: TObject; var Action: TCloseAction); private anchorX: Integer; anchorY: Integer; {location of the mouse click occurred} MouseX: Integer; MouseY: Integer; { Current position} Playersprite: tPlayersPrite; {TPL} BACKSPRITE: TBACKGROUNDSPRITE; {Game background diagram} end; const speed = 5; {Game character movement to each direction animation} Var mainform : TMAINFORM; Steps: Integer; {Parameters used to control the switching Elf animation picture} Implementation {$ r * .dfm} procedure tplayersprite.docollision (Sprite: Tsprite;
VAR DONE: BOOLEAN); Begin Done: = false; {I have detected collision, no longer repeat the detection collision} {Detection game character has collided with other elves, which can be expanded as a dialogue} End; Procedure TPlayersprite .Domove (MoveCount: Integer); Var L, R, D, U: Boolean; Absx, Absy: Integer; {The current location of the game character with the absolute distance of the destination} begin inherited Domove (MoveCount); MoveCount: = trunc MoveCount * 1.5); l: = false; r: = false; u: = false; d: = false; if (trunc (x) -mainform.anchorx> 0) THEN L: = True else r: = true; if; if; if; (Trunc (Y) -mainform.Anchory> 0) THEN u: = True else D: = true; ABSX: = ABS (Trunc (x) -mainform.Anchorx; Absy: = ABS (Trunc (Y) -mainform. Anchory; if Absx <4 THEN BEGIN L: = false; r: = false; end; if absy <4 The begin u: = false; d: = false; end; {If the absolute distance is less than four pixels, The destination is considered to be reached} if u and not d and not r dam (MoveT, DRUPLEFT); if u and r and not l and not d the MoveTo (MoveCount, DruPright); if D and L and NOT R And not u THEN MOVETO (MoveCount, DRDOWNLEFT); if D and r and not u and not l1 Moveto (MoveCount, DRDOWNRIGHT); if D and NOT L AND NOT R AND NTEN MOVETO (MoveCount, DRDOWN); IF u And not l and no T r and not d the moveto (MoveCount, Drup); if L and not u and not r and not d killeto; if r and not l and not u and not d The MoveTo (MoveCount, Drright) {Judging the direction of the movement according to the destination, thereby playing an animation of the corresponding direction motion} collision; {detection collision} Engine.x: = -x engine.width Div 2 - Width Div 2; engine.y: = -y ENGINE.HEIGHT DIV 2 - Height Div 2; {Moving Engine, thus the game character is in the stage of the stage. {Detection DXDRAW can draw, otherwise exit} DXINPUT.UPDATE; {capture various device inputs, here we used to detect the input of the mouse} lagcount: = 1000 DIV 60;
{DXSPRIENGINE.MOVE (LAGCOUNT); DxSpriteEngine.de (0); {DXSPRITEENGINE.DEAD; DXSPRITEENGINE.MOVE (0); {Plucking the entire screen as black} DXSPRITEENGINE.DRAW; with DXDRAW.SURFACE.CANVAS DO Begin brush.style :=bsclear; pen.style: = CLWHIT; font.color: = CLWHITE; font.ssize: = 10; Textout (10, 10, 'Press Esc to quit'; Textout (100,100, 'x:' INTOSTR (Anchorx) 'Y:' INTOSTR (Anchory)); {Mouse click to convert the coordinate in the game world after conversion} Textout (100, 200, 'Sprit x: INTTOSTR (Trunc (Playersprite.x)) 'Y:' INTOSTR (Trunc (PLAYERSPRITE.Y))); {Elf in the game world coordinate} Textout (100,300, 'Relative x:' INTSTR (Anchorx-Trunc) (Playersprite.x)) 'Y:' INTOSTR (Anchory-Trunc (Playersprite.y))))); {The absolute distance between the current position and the destination} Textout (200, 100, 'Mouse x:' INTSTR Mainform.mousex) 'Y:' INTOSTR (Mainform.Mousey)); {mouse current location, relative to the upper left corner of the window, not converted to the game world coordinate} Release; End; {Output corresponding parameters on the letter, used for Program debug} DXDraw.flip; {flip the background surface in the memory to the current and display} end; procedure tMainform.dxdrawFinalize (sender: TOBJECT); begin DXTimer.enabled: = false; {Close Timer} end; proc; edure TMainForm.DXDrawInitialize (Sender: TObject); begin DXTimer.Enabled: = True; {starting a timer} end; procedure TMainForm.FormCreate (Sender: TObject); begin Steps: = 0; AnchorX: = 0; AnchorY: = 0 ; MouseX: = 320; MouseY: = 240; {default mouse in the center of the screen so that} ImageList.Items.MakeColorTable; DXDraw.ColorTable: = ImageList.Items.ColorTable; DXDraw.DefColorTable: = ImageList.Items.ColorTable; DXDraw. UpdatePalette; {Update System Pattern} Backsprite: = tbackgroundsprite.create (DXSpriteEngine.Engine); with tbackgroundsprite (BACKSPRITE) DO BEGIN SETMAPSIZE (1, 1);
{Setting background display style is 1 × 1} image: = imagelist.Items.Find ('Background'); {Load Background Picture} z: = -2; {Setting Background Level} Tile: = true; { The background fill style is tile} end; playersprite: = tPlayersprite.Create (DXSPRIEEEEE.Create); with TPLAYERSPRITE (Playersprite) Do Begin Image: = imagelist.Items.Find ('player'); z: = 2; width: = Image.Width; Height: = image.height; end; {Load Game Character} End; Procedure TMAINFORM.FORMKEYDOWN (Sender: Tobject; var Key: Word; Shift: tshiftstate); begin {If you press ESC, exit } if Key = VK_ESCAPE then Close; {switch to full-screen mode and windowed mode} if (ssAlt in Shift) and (Key = VK_RETURN) then begin DXDraw.Finalize; if doFullScreen in DXDraw.Options then begin RestoreWindow; DXDraw.Cursor: = crNone; BorderStyle: = bsSizeable; DXDraw.Options: = DXDraw.Options - [doFullScreen]; end else begin StoreWindow; DXDraw.Cursor: = crNone; BorderStyle: = bsNone; DXDraw.Options: = DXDraw.Options [doFullScreen]; End; dxdraw.initialize; end; end; procedure tMainform.dxdrawmo Usedown (Sender: Tobject; Button: TMouseButton; Shift: TshiftState; x, y: integer; begin anchorx: = x trunc (playersprite.x) -320; Anchory: = y trunc (Playersprite.y) -240; {Convert the mouse to the position of the click on the screen to the game world} Playersprite.canmove: = true; {This parameter allows the mouse to drag} End; Procedure Tmainform.dxdrawMouseMove (Sender: Tobject; Shift: TshiftState; x, y: integer Begin if Playersprite.canmove thrun, anchorx: = x trunc (playersprite.x) -320; Anchory: = Y TRUNC (Playersprite.y) -240; {Click the mouse on the screen during the mouse drag The location is switched to the game world} end; mousex: = x; mousey: = y; {mouse current position} end; procedure tMAINFORM.DXDRAWMOUSEUSEUP (Sender: Tobject; Button: tmousebutton;
Shift: TShiftState; X, Y: Integer); begin PlayerSprite.CanMove: = False; end; procedure TMainForm.FormClose (Sender: TObject; var Action: TCloseAction); begin DXSpriteEngine.Free; end; procedure TPlayerSprite.MoveTo (MoveCount: INTEGER; DIRECTION: TDIRECTION; Begin {Control Elf Turn to Each Direction} Case Direction of Drup: Begin Y: = Y- (150/1000) * MoveCount; INC (Steps); Animpos: = Steps Div Speed 20 1 {Picture Sequence Number of Play in Current Animation} If Steps> 4 * Speed-2 Then Stes: = 0; End; DRDOWN: Begin Y: = Y (150/1000) * MoveCount; Inc (Steps); Animpos: = Steps Div Speed 1; if Steps> 4 * Speed-2 Then Stes: = 0; End; DRLLEFT: Begin x: = X- (150/1000) * MoveCount; Inc (Steps); Animpos: = Steps Div Speed 10 1; if steps> 4 * speed-2 Then Stes: = 0; end; drright: begin x: = x (150/1000) * MoveCount; Inc (steps); animpos: = Steps Div Speed 30 1; IF Steps> 4 * Speed-2 Then Stes: = 0; End; DRUPLEFT: Begin x: = x (150/1000) * MoveCount; Y: = Y- (150/1000) * MOVECO Unt; INC (Steps); Animpos: = Steps Div Speed 15 1; if Steps> 4 * Speed-2 Then Stes: = 0; End; Drupright: Begin x: = x (150/1000) * MoveCount; y : = Y- (150/1000) * MoveCount; INC (Steps); Animpos: = Steps Div Speed 25 1; if Steps> 4 * Speed-2 Then Steps: = 0; End; DRDOWNLEFT: Begin x: = X- (150/1000) * MoveCount; Y: = Y (150/1000) * MoveCount; Inc (steps); Animpos: = Steps Div Speed 5 1; if Steps> 4 * Speed-2 Then Steps: = 0; end; DRDOWNRIGHT: Begin x: = x (150/1000) * MoveCount;