?? rpg.cpp
字號:
/********************************************************
* 《圣劍英雄傳--英雄救美》測試版 *
* 中文RPG游戲源程序 *
* *
* softboy *
* 1999.6 *
* *
* http://goldpoint.126.com *
* mailto:wj77@163.net *
* *
* 本文件由 softboy 創建于 1999/3/25 *
* 最后修改于 1999年6月11日 *
* *
* 聲明: *
* 在不用于商業目的的前提下,你可以任意復制并 *
* 傳播該程序,如果愿意還可以自由更改,但由此產生 *
* 后果,我不負擔任何責任。 *
* 如果要將該程序用于商業目的,請事先與我聯系, *
* 否則,后果自負! *
********************************************************/
//聲明包含文件
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <mmsystem.h>
#include <time.h>
#include <direct.h>
#include <ddraw.h>
#include <dsound.h>
#include "ddutil.h"
#include "resource.h"
#define ScreenX 640 //屏幕寬
#define ScreenY 480 //屏幕高
#define ScreenColor 8 //顏色深度
#define MAPS 8 //游戲中總共的地圖數目
#define NPCS 15 //游戲中總共的NPC數目(種類)
#define TREASURE 0xf000 //地圖中的寶物偏移
#define BLAK 0xa000 //地圖中的障礙偏移值 即:障礙編號=BLAK+???
#define SPACE 0x5000 //地圖中的切換場景的偏移值(英雄踏上后切換到下一個場景)
#define BUY 1 //買
#define SALE 2 //賣
//================================全局變量聲明==================================
LPDIRECTSOUNDBUFFER SoundAo[10]; //挨打聲音
LPDIRECTSOUNDBUFFER SoundDead[10]; //死亡聲音
LPDIRECTSOUNDBUFFER SoundAttack[10]; //攻擊聲音
#include "dsound.cpp"
LPDIRECTDRAW lpDD; //DirectDraw對象
LPDIRECTDRAWSURFACE lpDDSPrimary; // 主頁面
LPDIRECTDRAWSURFACE lpDDSBack; // 緩沖頁面
LPDIRECTDRAWSURFACE lpDDSBackGround;// 背景頁面
LPDIRECTDRAWSURFACE lpDDSSpirit; // 精靈頁面
LPDIRECTDRAWSURFACE lpDDSNpc[NPCS]; // 電腦人物頁面
LPDIRECTDRAWSURFACE lpDDSMap1; // 地圖頁面1
LPDIRECTDRAWSURFACE lpDDSMap2; // 地圖頁面2
LPDIRECTDRAWSURFACE lpDDSDialog; // 對話框頁面
LPDIRECTDRAWSURFACE lpDDSStateBar; // 狀態頁頁面
LPDIRECTDRAWSURFACE lpDDSFightBar; // 打斗頁頁面
LPDIRECTDRAWSURFACE lpDDSBomb; // 爆炸頁面
LPDIRECTDRAWSURFACE lpDDSMainMenu; // 主菜單頁面
LPDIRECTDRAWSURFACE lpDDSGoods; // 物品頁面
LPDIRECTDRAWPALETTE lpDDPal; //主調色板
char *Talk; //游戲中的所有對話數據
HWND hWnd; //主窗口句柄
BOOL bActive = TRUE; //應用程序是否活躍
int Scene=0; //所處場景標志
int SX=0,SY=0; //所處場景的左上坐標
int old_SX=0, old_SY=0;
int DX=0,DY=0; //生成場景時的左上坐標
int old_DX=0, old_DY=0;
RECT rect; //Blt用的矩形
int Flag_OutCity=0; //出城的標志
int Flag_GotoPalace=0; //進魔宮的標志
//*********角色屬性結構**********
typedef struct{
int ID; //角色唯一編號
int Pic; //角色圖片編號
int Enemy; //角色是否是敵人
int TalkNum; //對話編號
BOOL Active; //角色是否活動
BOOL Show; //角色是否可見
char Name[32]; //角色名稱
int Width,Hight; //角色大小
int x,y; //當前坐標
int old_x,old_y; //舊的坐標
int Way; //方向
int Stats; //狀態
int Level; //等級
int Exp; //經驗
int Lift; //生命
int MaxLift; //生命最大值
int Attack; //攻擊
int Defend; //防御
int Speed; //速度
unsigned char Goods[17]; //物品(最多可帶16件)
int Money; //金錢
LPDIRECTDRAWSURFACE Surface; //角色的圖片
}Role;
Role Hero; //小飛刀的對象
//*********地圖結構**********
typedef struct{
char Name[32]; //名字
int Width; //寬
int Hight; //高
char Ground; //地面材料
char res[7]; //保留
unsigned short *Data; //數據
int Npc_Nums; //NPC數量
Role *NPC; //NPC鏈表
}Map_Struct;
Map_Struct Map[MAPS];
//********物品結構*********
typedef struct{
int ID; //編號
char Name[32]; //名字
char About[100]; //功能
int Money; //價值
int Exp,Lift,Attack,Defend; //作用
}Good_Struct;
Good_Struct Goods[20];
//函數聲明
LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
HWND InitWindow( HINSTANCE hInstance, int nCmdShow );
void GameTitle();
BOOL InitDDraw( void );
void FreeDDraw( void );
BOOL Blt(LPDIRECTDRAWSURFACE SS,int x,int y,LPDIRECTDRAWSURFACE DS,RECT rcRect,BOOL Flog);
void Flip(void);
HRESULT restoreAll( void );
BOOL initFail(char *str);
void MainMove();
void NpcMove();
void MainLoop();
void MessageLoop( int Msg );
BOOL LoadMaps();
BOOL LoadNpcData(int map);
int ReadLine(char *,int &,char *,int Seek=11);
void MakeBackGround();
void DrawNpc();
BOOL CreateBitmap(LPDIRECTDRAWSURFACE &lpTemp,int x,int y,char *BitmapFile, DWORD MemoryFlag=0);
RECT GetRect(int,int,int,int);
int random(int nMax);
BOOL SaveGame();
BOOL LoadGame();
int SaleDialog(Role Boss, int Flag=BUY);
int Fight(Role Enemy, int FightScene, int Escape=50);
#include "palette.cpp"
#include "textout.cpp"
#include "other.cpp"
#include "drawit.cpp"
#include "init.cpp"
#include "sale.cpp"
#include "fight.cpp"
#include "header.cpp"
#include "loadsave.cpp"
//****************************************************
//生成背景
void MakeBackGround()
{
unsigned short n;
for(int i=SY; i<SY+16 ; i++)
for(int j=SX; j<SX+21 ; j++)
{
//畫地面
RECT rect={ 0, Map[ Scene ].Ground *32, 32, Map[ Scene ].Ground * 32 +32};
Blt(lpDDSBackGround, DX+(j-SX)*32, DY+(i-SY)*32, lpDDSMap1, rect, FALSE);
//畫物體
n=Map[ Scene ].Data[ i * Map[ Scene ].Width + j ];
if( n>0 && n<SPACE || n>=BLAK )
{
if( n>=BLAK ) n-=BLAK; //障礙
if( n>=TREASURE-BLAK ) n=301; //寶物
rect=GetRect( n%20*32, n/20 * 32, n%20*32 + 32, n/20 * 32 + 32);
Blt(lpDDSBackGround, DX+(j-SX)*32, DY+(i-SY)*32, lpDDSMap2, rect, TRUE);
}
}
DrawNpc(); //畫NPC
}
//****************************************************
//生成該圖Npc
void DrawNpc()
{
for(int i=0; i<Map[Scene].Npc_Nums; i++)
if( Map[Scene].NPC[i].Show == 1 ) //如果NPC可見
{
rect=GetRect( Map[Scene].NPC[i].Stats* Map[Scene].NPC[i].Width, Map[Scene].NPC[i].Way*Map[Scene].NPC[i].Hight, Map[Scene].NPC[i].Stats*Map[Scene].NPC[i].Width+Map[Scene].NPC[i].Width, Map[Scene].NPC[i].Way* Map[Scene].NPC[i].Hight+Map[Scene].NPC[i].Hight);
Blt(lpDDSBackGround, Map[Scene].NPC[i].x-(SX*32)+DX, Map[Scene].NPC[i].y-(Map[Scene].NPC[i].Hight)-(SY*32)+DY, Map[Scene].NPC[i].Surface, rect, TRUE);
}
}
//****************************************************
//主角行走函數
void MainMove()
{
//邊界障礙物檢測
int n0 = ((Hero.y-20-DY)/32 + SY) * Map[ Scene ].Width + ((Hero.x+12-DX)/32 + SX);
int n1 = ((Hero.y-20-DY)/32 + SY) * Map[ Scene ].Width + ((Hero.x+20-DX)/32 + SX);
int n2 = ((Hero.y-12-DY)/32 + SY) * Map[ Scene ].Width + ((Hero.x+12-DX)/32 + SX);
int n3 = ((Hero.y-12-DY)/32 + SY) * Map[ Scene ].Width + ((Hero.x+20-DX)/32 + SX);
if( Map[ Scene ].Data[n0] >= BLAK || Map[ Scene ].Data[n1] >= BLAK || Map[ Scene ].Data[n2] >= BLAK || Map[ Scene ].Data[n3] >= BLAK )
{
Hero.x=Hero.old_x;
Hero.y=Hero.old_y;
SX = old_SX; SY = old_SY;
DX = old_DX; DY = old_DY;
}
//NPC碰撞檢測
for(int i=0; i<Map[Scene].Npc_Nums; i++)
{
if( Map[Scene].NPC[i].Show==1 &&\
abs(Hero.x+SX*32-DX - Map[ Scene ].NPC[i].x)<=24 &&\
abs(Hero.y+SY*32-DY - Map[Scene].NPC[i].y)<=24 )
{
Hero.x=Hero.old_x;
Hero.y=Hero.old_y;
SX = old_SX; SY = old_SY;
DX = old_DX; DY = old_DY;
}
}
MakeBackGround();
RECT rect1={0,0,ScreenX,ScreenY};
Blt(lpDDSBack, 0, 0, lpDDSBackGround, rect1, FALSE);
//在新位置畫英雄
RECT rect2={Hero.Stats*Hero.Width, Hero.Way*Hero.Hight, Hero.Stats*Hero.Width+Hero.Width, Hero.Way*Hero.Hight+Hero.Hight};
Blt(lpDDSBack, Hero.x, Hero.y - Hero.Hight, lpDDSSpirit, rect2, TRUE);
/*
//重畫可遮蓋英雄的物體
int n = ((Hero.y-17-DY)/32 + SY) * Map[ Scene ].Width + ((Hero.x+16-DX)/32 + SX);
if( Map[ Scene ].Data[n+Map[ Scene ].Width] >= BLAK )
{
int num=Map[ Scene ].Data[ n+Map[ Scene ].Width ] - BLAK;
RECT rect3={ 0, num * 32, 32, num * 32 + 32};
Blt(lpDDSBack, DX + ( n%Map[ Scene ].Width - SX)*32 , DY + ( n/Map[ Scene ].Width+1 - SY)*32, lpDDSMap2, rect3, TRUE);
}
if( Map[ Scene ].Data[n+Map[ Scene ].Width+1] >= BLAK )
{
int num=Map[ Scene ].Data[ n+Map[ Scene ].Width+1 ] - BLAK;
RECT rect4={ 0, num * 32, 32, num * 32 + 32};
Blt(lpDDSBack, DX + ((n+1)%Map[ Scene ].Width-SX)*32, DY + (n/Map[ Scene ].Width+1-SY)*32, lpDDSMap2, rect4, TRUE);
}
*/
Hero.old_x=Hero.x;
Hero.old_y=Hero.y;
old_SX = SX; old_SY = SY;
old_DX = DX; old_DY = DY;
}
//****************************************************
//游戲主循環
void MainLoop()
{
static long old_clock, new_clock; //延時變量
new_clock=GetTickCount();
if( new_clock > old_clock + 30 )
{
old_clock=new_clock;
//如果按鍵
if( GetAsyncKeyState(VK_CONTROL) || GetAsyncKeyState(VK_RETURN) )
{
OnKeyDown();
}
//檢測方向鍵
if(GetAsyncKeyState(VK_UP)) //上
{
Hero.Way=3;
if( SY>0 && Hero.y <= 264 )
{
DY += Hero.Speed;
if( DY>=0 ) { DY=-32; SY--; }
}
else if( SY==0 && DY!=0 )
{
DY += Hero.Speed;
}
else Hero.y -= Hero.Speed;
}
else if(GetAsyncKeyState(VK_DOWN)) //下
{
Hero.Way=0;
if( SY < Map[ Scene ].Hight - 15 && Hero.y >=264 )
{
DY -= Hero.Speed;
if( DY<=-32 ) { DY=0; SY++; }
}
else Hero.y += Hero.Speed;
}
else if(GetAsyncKeyState(VK_LEFT)) //左
{
Hero.Way=1;
if( SX>0 && Hero.x <= 304 )
{
DX += Hero.Speed;
if( DX>=0 ) { DX=-32; SX--; }
}
else if( SX==0 && DX!=0 )
{
DX += Hero.Speed;
}
else Hero.x -= Hero.Speed;
}
else if(GetAsyncKeyState(VK_RIGHT)) //右
{
Hero.Way=2;
if( SX < Map[ Scene ].Width - 20 && Hero.x >= 304 )
{
DX -= Hero.Speed;
if( DX<=-32 ) { DX=0; SX++; }
}
else Hero.x += Hero.Speed;
}
else if(GetAsyncKeyState(VK_ESCAPE)) //主菜單
{
while(GetAsyncKeyState(VK_ESCAPE)) {}
Menu();
return;
}
else return;
//邊界檢測
if( Hero.x<0 ) Hero.x=0;
if( Hero.x>ScreenX-Hero.Width ) Hero.x=ScreenX-Hero.Width;
if( Hero.y<Hero.Hight-16 ) Hero.y=Hero.Hight-16;
if( Hero.y>ScreenY ) Hero.y=ScreenY;
if( SX < 0 ) SX=0;
if( SX > Map[ Scene ].Width - 20 ) SX=Map[ Scene ].Width -20;
if( SY < 0 ) SY=0;
if( SY > Map[ Scene ].Hight - 15 ) SY=Map[ Scene ].Hight -15;
Hero.Stats++;
if( Hero.Stats>=3 ) Hero.Stats=0;
MainMove();
Flip();
//進入消息循環
int n = ((Hero.y-16-DY)/32 + SY) * Map[ Scene ].Width + ((Hero.x+16-DX)/32 + SX);
MessageLoop( Map[ Scene ].Data[ n ] );
}
}
//***********************************************************
//消息循環
void MessageLoop( int Msg )
{
switch( Msg )
{
case SPACE+0: //出城
//第一次到城們
if( Flag_OutCity==0 )
{
Hero.y=Hero.old_y=450;
ShowDialog(5, 30001, 0);
break;
}
else if( Flag_OutCity==1 ) //可以出城了
{
Flag_OutCity=2;
Hero.y=Hero.old_y=450;
ShowDialog(5, 30001, 1);
for(int i=0; i<Map[ Scene ].Npc_Nums; i++)
{
Map[ Scene ].NPC[i].TalkNum=1;
Map[ Scene ].NPC[i].Speed=12;
}
break;
}
Scene = 2;
SX=SY=DX=DY=0;
Hero.x=Hero.old_x=32; Hero.y=Hero.old_y=2*32;
ChangePalette(MainPal,NullPal,-1);
MainMove();
Flip();
ChangePalette(NullPal,MainPal,1);
break;
case SPACE+1: //回城
Scene = 1;
SX=7; DX=0;
SY=11; DY=0;
Hero.x=Hero.old_x=350; Hero.y=Hero.old_y=450;
ChangePalette(MainPal,NullPal,-1);
MainMove();
Flip();
ChangePalette(NullPal,MainPal,1);
break;
case SPACE+2: //出門
Scene = 1;
SX=14; DX=0;
SY=0; DY=0;
Hero.x=Hero.old_x=384; Hero.y=Hero.old_y=100;
ChangePalette(MainPal,NullPal,-1);
MainMove();
Flip();
ChangePalette(NullPal,MainPal,1);
break;
case SPACE+3: //回家
Scene = 0;
SX=0; DX=0;
SY=0; DY=0;
Hero.x=Hero.old_x=410; Hero.y=Hero.old_y=400;
ChangePalette(MainPal,NullPal,-1);
MainMove();
Flip();
ChangePalette(NullPal,MainPal,1);
break;
case SPACE+9: //進神殿
//第一次進神殿
if( Flag_GotoPalace==0 )
{
//Flag_GotoPalace=1;
Hero.y=Hero.old_y=450;
ShowDialog(0, 30002, 0);
break;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -