Rogue游戏(三)——怪物、战斗、战争迷雾

Rogue游戏中需要有怪物和战斗,我们采取简单的战斗系统,即战斗双方各有攻击力和防御力,回合制攻击直至一方死亡。战争迷雾的设计可以使得游戏者有探索地图的乐趣。

Makefile同上一篇文章

main.cpp

#include <curses.h>
#define EMPTY 0
#define ME 1
	#define ME_ATK 10
	#define ME_DEF 15
	#define ME_HP 100
#define WALL 2
#define IN 4
#define OUT 5
#define MONSTER_A 3
	#define A_ATK 20 
	#define A_DEF 2
	#define A_HP 20
	#define A_EXP 20
#define INSTRUCTION mvprintw(0, 0, "My Rogue\na/left w/up s/down d/right q/exit r/restart");
#include <stdlib.h>
static char symbol[] = {'.', '@', '#', 'A', '(', ')'};
static const int m_w = 90;
static const int m_h = 22;
static const int offset_x = 5;
static const int offset_y = 2;
static int **map;
void MakeMap(int _w, int _h, int **_map);
void drawMap()
{
	for (int i = 0;i < m_w;++i)
		for (int j = 0;j < m_h;++j)
			mvaddch(j + offset_y, i + offset_x, symbol[map[j][i]]);
}
class spirit
{
protected:
	int x;
	int y;
	int kind;
	int hp;
	int atk;
	int def;
public:
	spirit(){}
	spirit(int _x, int _y, int _kind)
	{
		x = _x;
		y = _y;
		kind = _kind;
		switch(kind)
		{
			case MONSTER_A:
				atk = A_ATK;
				def = A_DEF;
				hp = A_HP;
				break;
		}
	}
	virtual void ShowStatus(){}
	bool isDead()
	{
		if (hp <= 0)
			return true;
		return false;
	}
	void attack(spirit *aim)
	{
		aim->defend(this, atk);
	}
	void defend(spirit *aim, int _atk)
	{
		if (def >= _atk)
			return;
		hp -= (_atk - def);
		if (!isDead())
			attack(aim);
	}
	void FightToDeath(spirit *aim)
	{
		while(1)
		{
			attack(aim);
			if (aim->isDead() || isDead())
				break;
		}
	}
};
class human:public spirit
{
	int level;
	int exp;
public:
	human(int _kind);
	void Move(int _dir);
	void ShowMove(int fx, int fy, int tx, int ty);
	virtual void ShowStatus();
	void ShowView();
	void GainExp(int _kind);
	void LevelUp();
}*me;
human::human(int _kind)
{
	kind = _kind;
	level = 1;
	exp = 0;
	do
	{
		x = rand() % m_w;
		y = rand() % m_h;
	}while(map[y][x] != 0);
	atk = ME_ATK;
	def = ME_DEF;
	hp = ME_HP;
	mvaddch(y + offset_y, x + offset_x, symbol[kind]);
	refresh();
}
void human::Move(int _dir)
{
	if (isDead())
		return;
	int dir_x[4] = {-1, 0, 1, 0};
	int dir_y[4] = {0, 1, 0, -1};
	int old_x = x;
	int old_y = y;
	x += dir_x[_dir];
	y += dir_y[_dir];
	if (map[y][x] == WALL)
	{
		x = old_x;
		y = old_y;
		return;
	}
	if (map[y][x] == MONSTER_A)//fight with monster(A kind)
	{
		spirit temp_m(x, y, map[y][x]);
		FightToDeath(&temp_m);
		if (isDead())
		{
			clear();
			INSTRUCTION
			mvprintw(offset_y+m_h/2, offset_x+m_w/2, "You are dead!");
			refresh();
			return;	
		}
		map[y][x] = EMPTY;
		GainExp(MONSTER_A);
	}
	ShowMove(old_x, old_y, x, y);
	ShowStatus();
	ShowView();
	refresh();
}
void human::ShowMove(int fx, int fy, int tx, int ty)
{
	mvaddch(fy + offset_y, fx + offset_x, symbol[EMPTY]); //EMPTY
	mvaddch(ty + offset_y, tx + offset_x, symbol[this->kind]);
}
void human::ShowStatus()
{
	mvprintw(offset_y, offset_x + m_w +1, "status of %c   ", symbol[kind]);
	mvprintw(offset_y+2, offset_x + m_w +1, "HP:%d   ", hp);
	mvprintw(offset_y+3, offset_x + m_w +1, "ATK:%d   ", atk);	
	mvprintw(offset_y+4, offset_x + m_w +1, "DEF:%d   ", def);	
	mvprintw(offset_y+5, offset_x + m_w +1, "LEV:%d   ", level);	
	mvprintw(offset_y+6, offset_x + m_w +1, "EXP:%d   ", exp);	
}
void human::ShowView()
{
	int dx[8] = {0, 0, 1, 1, 1, -1, -1, -1};
	int dy[8] = {1, -1, 1, 0, -1, 1, 0, -1};
	for (int i = 0;i < 8;++i)
		mvaddch(offset_y+y+dy[i], offset_x+x+dx[i], symbol[map[y+dy[i]][x+dx[i]]]);
}
void human::GainExp(int _kind)
{
	switch(_kind)
	{
		case MONSTER_A: exp += A_EXP;break;
	}
}
void InitGame()
{
	clear();
	if (me != NULL)
		delete me;
	MakeMap(m_w, m_h, map);
	me = new human(ME);
	me->ShowStatus();
	me->ShowView();
	INSTRUCTION
	refresh();
}
int main()
{
	initscr();
	noecho();
	curs_set(0);
	map = new int*[m_h];
	for (int i = 0;i < m_h;++i)
		map[i] = new int[m_w];
	InitGame();
	while(1)
	{
		char order = getch();
		if (order == 'q') break;
		switch(order)
		{
			case 'a': me->Move(0);break;
			case 's': me->Move(1);break;
			case 'd': me->Move(2);break;
			case 'w': me->Move(3);break;
			case 'r': InitGame();break;
		}
	}
	for (int i = 0;i < m_h;++i)
		delete []map[i];
	delete []map;
	delete me;
		endwin();
	return 0;
}
makemap.cpp

#include <stdlib.h>
#include <time.h>
#define ROOM_MIN_W 5
#define ROOM_MIN_H 4
#define ROOM_MAX_W 10
#define ROOM_MAX_H 7
#define ROOM_NUM 10
#define MONSTER_NUM 10
#define MAX_TRY 300
#define EMPTY 0
#define WALL 2
#define ME 1
#define IN 4
#define OUT 5
#define MONSTER_A 3
class room
{
public:
	int x;
	int y;
	int w;
	int h;
	bool TryCreateRoom(int _w, int _h, int **map)
	{
		do
			w = rand() % (ROOM_MAX_W + 1);
		while(w < ROOM_MIN_W);
		do
			h = rand() % (ROOM_MAX_H + 1);
		while(h < ROOM_MIN_H);
		x = rand() % (_w + 1);
		y = rand() % (_h + 1);
		if (x + w > _w || y + h > _h)
			return false;
		for (int i = x;i < x + w;++i)
			for (int j = y;j < y + h;++j)
			{
				if (map[j][i] != WALL || i == 0 || i == _w-1 || j == 0 || j == _h-1)
					return false;
			}
		return true;
	}
	bool CreateRoom(int _w, int _h, int **map)
	{
		for (int i = 0;i < MAX_TRY;++i)
			if (TryCreateRoom(_w, _h, map))
			{
				for (int ii = x;ii < x + w;++ii)
					for (int jj = y;jj < y + h;++jj)
						map[jj][ii] = 0;
				return true;
			}
		return false;
	}
};
void MakePassageWay(int fx, int fy, int tx, int ty, int **map)
{
	for (int i = 0;i <= tx || i <= fx;++i)
		if (map[fy][i] == WALL 
			&& ((i <= tx && i >= fx)||(i >= tx && i <= fx)))
			map[fy][i] = EMPTY;
	for (int i = 0;i <= ty || i <= fy;++i)
		if (map[i][tx] == WALL 
			&& ((i <= ty && i >= fy)||(i >= ty && i <= fy)))
			map[i][tx] = EMPTY;
}
void LinkRoom(room *_r1, room *_r2, int **map)
{
	MakePassageWay(_r1->x+_r1->w/2, _r1->y+_r1->h/2, _r2->x+_r2->w/2, _r2->y+_r2->h/2, map);
}
void MakeMap(int _w, int _h, int **map)
{
	srand((unsigned)time(NULL));
	for (int i = 0;i < _w;++i)
		for (int j = 0;j < _h;++j)
			map[j][i] = WALL;
	room r[ROOM_NUM];
	r[0].CreateRoom(_w, _h, map);//generate room
	for (int i = 1;i < ROOM_NUM;++i)
		if (r[i].CreateRoom(_w, _h, map))
			LinkRoom(&r[i-1], &r[i], map);
	for (int i = 0;i < MONSTER_NUM;++i)//generate monster A
	{
		int x, y;
		for (int ii = 0;ii < MAX_TRY;++ii) 
		{
			x = rand() % _w;
			y = rand() % _h;
			if (map[y][x] == EMPTY)
			{
				map[y][x] = MONSTER_A;
				break;
			}
		}
	}
	while(1)
	{
		int x = rand() % _w;
		int y = rand() % _h;
		if (map[y][x] == EMPTY)
		{
			map[y][x] = IN;
			break;
		}
	}
	while(1)
	{
		int x = rand() % _w;
		int y = rand() % _h;
		if (map[y][x] == EMPTY)
		{
			map[y][x] = OUT;
			break;
		}
	}
	return;
}
效果如下图:


全部探索完地图:



  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值