全资源免费下载
tool.h
#pragma once
#include<easyx.h>
void drawImg(int x, int y, IMAGE* src) {
DWORD* pwin = GetImageBuffer();
DWORD* psrc = GetImageBuffer(src);
int win_w = getwidth();
int win_h = getheight();
int src_w = src->getwidth();
int src_h = src->getheight();
//计算 贴图的实际长宽
int real_w = (x + src_w > win_w) ? win_w - x : src_w;
int real_h = (y + src_h > win_h) ? win_h - y : src_h;
if (x < 0) { psrc += -x; real_w -= -x; x = 0; }
if (y < 0) { psrc += (src_w * -y); real_h -= -y; y = 0; }
//修正贴图起始位置
pwin += (win_w * y + x);
//实现透明贴图
for (int iy = 0; iy < real_h; iy++) {
for (int ix = 0; ix < real_w; ix++) {
byte a = (byte)(psrc[ix] >> 24);
if (a > 100) {
pwin[ix] = psrc[ix];
}
}
//换到下一行
pwin += win_w;
psrc += src_w;
}
}
main.cpp
#include<iostream>
using namespace std;
#include<easyx.h>
#include<fstream>
#include<stdio.h>
#include"tool.h"
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
//游戏场景定义
#define AIR '0'
//游戏区外面
#define SPACE '1'
//空地
#define BOX '2'
//箱子
#define WALL '3'
//墙体
#define DEST '4'
//目的地
//定义窗口宽度和高度
#define W 640
#define H 640
//定义每个格子的宽度
#define SIZE 40
//箱子最大数目
#define MAXNUM 30
//自定义坐标类型
typedef struct {
int x;
int y;
}locate;
//存储目的地,待会用来判断是否胜利
typedef struct {
int num;
//目的地的数量
locate dest[MAXNUM];
//每个目的地的坐标
}Dests;
Dests d;
//目的地
int level;
//关卡
//读取关卡
void LoadLevel() {
ifstream ifs;
char tmp[10];
ifs.open("./level/level.txt", ios::in);
while (ifs >> tmp) {}
level = atoi(tmp);
ifs.close();
}
//写入关卡
void WriteLevel(int a) {
ofstream ofs;
char tmp[20];
sprintf(tmp, "%d", a);
ofs.open("./level/level.txt", ios::out);
ofs << tmp<< endl;
ofs.close();
}
//定义地图的类
class Map {
friend class Person;
public:
Map();
//初始化地图数据
void Draw();
//绘制地图
private:
char map[H / SIZE+1][W / SIZE];
//地图数据(不包括人物和箱子)
};
//定义箱子的类
class Box{
friend class Person;
public:
Box();
//初始化箱子数据
void Draw(Dests& d);
//绘制箱子
bool IsWin(Map& m);
//用来判断是否胜利
private:
int num;
//箱子的数目
locate box[MAXNUM];
//每个箱子的坐标
};
//定义角色的类
class Person {
public:
Person();
//初始化角色数据
void Draw();
//绘制角色
void Move(Map& m, Box& b);
//移动
bool IsBox(Box& b, int x, int y);
//用来判断移动路径上的两个箱子是否靠在一起
private:
int x, y;
//角色的坐标
};
int main() {
int n;
a:
cout << "请输入关卡(1-6):";
cin >> n;
if (n < 1 || n>6) {
cout << "输入错误!"<<endl;
goto a;
}
level = n - 1;
initgraph(W, H,0);
//背景音乐
mciSendString("open bk.mp3", 0, 0, 0);
mciSendString("play bk.mp3 repeat", 0, 0, 0);
table:
//关卡设置
level++;
if (level == 7) {
closegraph();
cout << "恭喜通关!" << endl;
return 0;
}
char str[10];
sprintf(str, "第%d关", level);
Map m;
Box box;
Person one;
//游戏
while (1) {
one.Move(m,box);
BeginBatchDraw();
cleardevice();
m.Draw();
outtextxy(5, 5, str);
box.Draw(d);
one.Draw();
EndBatchDraw();
FlushBatchDraw();
if (box.IsWin(m)) {
//WriteLevel(level);
break;
}
Sleep(80);
};
d.num = 0;
goto table;
return 0;
}
//初始化地图数据
Map::Map() {
ifstream ifs;
char str[20];
sprintf(str, "./level/%d_map.txt", level);
ifs.open(str, ios::in);
int i = 0;
while (ifs >> this->map[i]) {
i++;
}
ifs.close();
for (int i = 0; i < H / SIZE; i++) {
for (int j = 0; j < W / SIZE; j++) {
if (this->map[i][j] == '4') {
d.num++;
d.dest[d.num - 1].x = j * SIZE;
d.dest[d.num - 1].y = i * SIZE;
}
}
}
}
//绘制地图
void Map::Draw() {
IMAGE bk;
loadimage(&bk, "./bk.jpg", W, H);
putimage(0, 0, &bk);
for (int i = 0; i < H / SIZE; i++) {
for (int j = 0; j < W / SIZE; j++) {
int x = j * SIZE;
int y = i * SIZE;
//空地
if (this->map[i][j] == SPACE) {
setfillcolor(RGB(210, 210, 210));
fillrectangle(x, y, (x + SIZE), (y + SIZE));
}
//墙体
if (this->map[i][j] == WALL) {
IMAGE a;
loadimage(&a, "./wall.png", SIZE, SIZE);
putimage(x, y, &a);
}
//目的地
if (this->map[i][j] == DEST) {
setfillcolor(RGB(210, 210, 210));
fillrectangle(x, y, (x + SIZE), (y + SIZE));
IMAGE a;
loadimage(&a, "./dest.png", SIZE, SIZE);
drawImg(x, y, &a);
//调用"tool.h"头文件当中的接口实现透明贴图
}
}
}
}
//初始化箱子数据
Box::Box() {
this->num = 0;
ifstream ifs;
char str[20];
sprintf(str, "./level/%d_box.txt", level);
ifs.open(str, ios::in);
char tmp[20];
int i = 0;
int j = 0;
while (ifs >> tmp) {
if (i == 0) {
this->box[j].x = atoi(tmp)*SIZE;
}
if (i == 1) {
this->box[j].y = atoi(tmp)*SIZE;
}
i++;
if (i == 2) {
i = 0;
j++;
this->num++;
}
}
ifs.close();
}
//绘制箱子
void Box::Draw(Dests& d) {
for (int i = 0; i < this->num; i++) {
IMAGE a;
int status = 0;
for (int m = 0; m < d.num; m++) {
if (d.dest[m].x == this->box[i].x && d.dest[m].y == this->box[i].y) {
loadimage(&a, "./box_ok.png", SIZE, SIZE);
drawImg(this->box[i].x, this->box[i].y, &a);
status = 1;
break;
}
}
if (status == 0) {
loadimage(&a, "./box.png", SIZE, SIZE);
drawImg(this->box[i].x, this->box[i].y, &a);
}
}
}
//初始化角色数据
Person::Person() {
ifstream ifs;
char str[20];
sprintf(str, "./level/%d_role.txt", level);
ifs.open(str, ios::in);
char tmp[20];
int i = 0;
while (ifs >> tmp) {
if (i == 0) {
this->x = atoi(tmp) * SIZE;
}
if (i == 1) {
this->y = atoi(tmp) * SIZE;
}
i++;
}
ifs.close();
}
//绘制角色
void Person::Draw() {
IMAGE a;
loadimage(&a, "./one.png", SIZE, SIZE);
drawImg(this->x, this->y, &a);
}
//移动
void Person::Move(Map& m,Box& b) {
//获取人物在二维数组中的坐标
int j = this->x / SIZE;
int i = this->y / SIZE;
//用来判断前面是否有箱子
int status = 0;
//按下移动键
if (GetAsyncKeyState('W')) {
for(int n = 0; n < b.num; n++) {
//如果前面有箱子
if (b.box[n].x == this->x && b.box[n].y == this->y - SIZE) {
status = 1;
//如果箱子后面不靠墙也不靠箱子
if (m.map[i-2][j] != WALL&&!this->IsBox(b,b.box[n].x,b.box[n].y-SIZE)) {
b.box[n].y -= SIZE;
this->y -= SIZE;
}
}
}
//空地移动
if ((m.map[i - 1][j] == SPACE || m.map[i - 1][j] == DEST)&&(status!=1)) {
this->y -= SIZE;
}
return;
}
if (GetAsyncKeyState('S') ) {
for (int n = 0; n < b.num; n++) {
//如果前面有箱子
if (b.box[n].x == this->x && b.box[n].y == this->y + SIZE) {
status = 1;
//如果箱子后面不靠墙也不靠箱子
if (m.map[i + 2][j] != WALL && !this->IsBox(b, b.box[n].x, b.box[n].y + SIZE)) {
b.box[n].y += SIZE;
this->y += SIZE;
}
}
}
//空地移动
if ((m.map[i + 1][j] == SPACE || m.map[i + 1][j] == DEST) && (status != 1)) {
this->y += SIZE;
}
return;
}
if (GetAsyncKeyState('A')) {
for (int n = 0; n < b.num; n++) {
//如果前面有箱子
if (b.box[n].y == this->y && b.box[n].x == this->x - SIZE) {
status = 1;
//如果箱子后面不靠墙也不靠箱子
if (m.map[i][j-2] != WALL && !this->IsBox(b, b.box[n].x-SIZE, b.box[n].y )) {
b.box[n].x -= SIZE;
this->x -= SIZE;
}
}
}
//空地移动
if ((m.map[i][j-1] == SPACE || m.map[i][j-1] == DEST) && (status != 1)) {
this->x -= SIZE;
}
return;
}
if (GetAsyncKeyState('D')) {
for (int n = 0; n < b.num; n++) {
//如果前面有箱子
if (b.box[n].y == this->y && b.box[n].x == this->x + SIZE) {
status = 1;
//如果箱子后面不靠墙也不靠箱子
if (m.map[i][j + 2] != WALL && !this->IsBox(b, b.box[n].x+SIZE, b.box[n].y )) {
b.box[n].x += SIZE;
this->x += SIZE;
}
}
}
//空地移动
if ((m.map[i][j+1] == SPACE || m.map[i][j+1] == DEST) && (status != 1)) {
this->x += SIZE;
}
return;
}
}
//用来判断移动路径上的两个箱子是否靠在一起
bool Person::IsBox(Box& b, int x, int y) {
for (int i = 0; i < b.num; i++) {
if (b.box[i].x == x && b.box[i].y == y)return true;
}
return false;
}
//用来判断是否胜利
bool Box::IsWin(Map& m) {
int count = 0;
for (int i = 0; i < d.num; i++) {
for (int j = 0; j < this->num; j++) {
if (this->box[j].x == d.dest[i].x && this->box[j].y == d.dest[i].y) {
count++;
}
}
}
if (count == d.num) {
return true;
}
return false;
}