矩阵结构体 图片绘制 超级玛丽demo6

难度预警!!!

一些结构体 的碎碎念

在之之前我们的结构体中,我们在里面写了成员函数,这样其实是错误的。我们之前是迫于无奈必须要用函数。

通常来说不允许这样使用,只让你使用成员变量。

在class 中 成员变量是隐藏的,不让你直接访问,通常要通过成员函数get set 方法 来访问。在大一新手村的时候我们早已滚瓜烂熟了。

矩形碰撞函数

我们一样用头文件来实现这个功能 名字就起做MyRect

-> 相当于 (*p). 解引用访问

映射 map

数据结构

线 树 图

真正的数据结构其实只有线,树其实是一种算法,使用的时候都是搭配一些高阶算法使用。

图是牵扯到架构 和 设计 方向的,网络地图等等东西,这玩意效率不高 最好不超过32个。

unity3d 用的碰撞检测用的是有序图,最多添加32个 多了不能添加了。

线性结构有很多经典的算法 图结构算法太多了,每个问题都有自己的算法

之后我们还要复习新手村学的 链表 线性表

map

树形结构 红黑树

迭代器 iterator

打包两个东西 随意组合两个数据 而且能容纳不同类型

定义一个类型的数据 我们称为bmpmap

这里面包含一些函数

find() 查找键值对

这里的 iterator 也是官方提供的 我们取名叫 it

键值对

pair<数据类型1,数据类型2>(数据1,数据2)

.insert()

这样就能在 我们的bmp map中存储我们的数据

在demo5的基础上改进

我们用一点面向对象的思想,我们最早的draw1.0版本 是编码一个图素,后来我们又改进成了2.0版本,也就是给定坐标和宽高,现在我们想进一步改进。

先定义一个 矩形结构体,这个矩形为了编程方便,并没有使用 四个角,而是给出了四条直线围成的矩形,方便后续编程。

struct MYRECT

MyRect.h

然后实现对应方法:

MyRect.cpp

这两个 一个是碰撞检测前面我们讲过了

一个是设置矩形 这里我们只需要 给定左上角坐标 矩形的宽和高 就可以设置好一个矩形,并且转换为 四个边的坐标,四个边的坐标更容易编程。

struct BMP

BMP 是 Bitmap(位图)的缩写,代表一种无损的栅格图像文件格式。该格式由微软开发,最初用于 Windows 操作系统存储图像数据。由于它以像素矩阵(位图)形式保存图像信息,因此得名"位图文件格式"(Bitmap File)。

  • PNG:支持无损压缩,文件更小且透明通道。
  • JPEG:有损压缩,适合照片但牺牲部分画质。
  • BMP 的局限性:因未压缩导致占用空间大,现代应用逐渐减少。

这里我们是用控制台模拟的BMP。

我们在 GameDraw.h 中重新定义了一个结构体 BMP

这里我们把它的对应方法全部放在了GAMEDRAW里面,为了模拟结构体的正确用法。

BMP 只有宽高 和对应容量 这里的BMP是搭配使用的我们 我们继续改进OBJ这个 结构体 来进行管理。

struct OBJ

1.0 版本

在1.0版本中 我们只能绘制单一的图素 而且只能是长方形 这个功能就很积累 今天我们升级一下。

在OBJ2.0 中我们 把tis 和 w,h 这个东西换成了 cosnt cahr* key

这是什么呢?

这就是 拿来放 BMP 用的,当然 这里还没有 把BMP 和key 配合使用起来。

我们在上面的内容里介绍过的map 红黑树 就是用在这里

bool AddBmp(const char* key, BMP bmp);

我们已经知道 在OBJ里 图素被替换成了 const char* key 也就是一个字符串

这里我们是用来存放 bmp的索引的,那么怎么将 key字符串 和 bmp 绑定起来呢?

于是我们在 GameDraw.cpp 里面 性写了一个方法 bool AddBmp(const char* key, BMP bmp);

这个方法很贱单,使用的时候 传入一个 OBJ里的字符串key 和 一个创建好大小的BMP

先判断是否为空字符串

然后 我们用map 搞一个迭代器 std::map<const char*, BMP>::iterator it;

这个迭代器 是 const char* 和 结构体BMP 的组合类型。

注意这里使用map需要加头文件 #include <map>

我们提前在 GAMEDRAW 结构体中 创建出 bmpmap 红黑树对象

然后记住这个用法 就是 it用来接收 是否找到东西

it = bmpmap.find(key);

这里的返回值 我们并不关心 可以这样理解 it 就是指向这个bmpmap 的一个特殊的指针

这里可以存放返回的结果。

如果找到了 就可以指向 这个键值对

如果 it == bmpmap.end();

那就添加不了

就说明已经迭代到了最后一个 还是没有,就是没有 就可以添加上 这个键值对

添加的时候是这样使用的

首先 我们要知道怎么手动创造一个键值对

std::pair<const char*, BMP>(key, bmp)

然后把这个键值对添加到 bmpmap中 使用的是 insert方法

bmpmap.insert(std::pair<const char*, BMP>(key, bmp));、

完整的代码时这样的

cpp 复制代码
bool GAMEDRAW::AddBmp(const char* key, BMP bmp)
{
	if (key == 0)
		return false;
	//用key 直接查找 是否有数据
	std::map<const char*, BMP>::iterator it;
	it = bmpmap.find(key);

	if (it != bmpmap.end())
		return false;
	
	bmpmap.insert(std::pair<const char*, BMP>(key, bmp));
	return true;
}

bool Draw(const char* key, int x ,int y);

要知道 我们之前的draw 函数1.0 是画一个图素 2.0 是在一个矩形范围内画一个图素

这里 的3.0 是画一个bmp

这是我们2.0 的draw 函数

现在 我们直接改成 画BMP

那就是给 key ,x,y 就可以

首先 key 为空 , key中找不到BMP都直接返回false,记住只要找map里的东西 都要创建迭代器

接着 才是我们的 draw 功能

首先 我们怎么拿到这个 BMP呢? 很简单迭代器的第一个元素叫first 第二个元素叫 second

直接用指针 来指向这个 BMP 然后就拿到了

我们用 p -> 就可以拿到 BMP的 w,h 还有 _map[100]

然后进行绘制 这里注意 的是 只有 _map[i] 不等于0才绘制 这样在没有东西的地方 相当于BMP就透明了

这里自己 实现一下就好了

源.cpp

这里有变化的是 BMP我们要创建一下

几个量我们都初始化然后赋值就可以了

这里我们用了一个 {} 作用是释放内存。

效果完成!

附上工程源码:

MyRect.h

cpp 复制代码
#pragma once

struct MYRECT {
	int left, top, right, bottom;

	bool Sollider(const MYRECT& other);
	bool Set(int x, int y, int w, int h);
};

MyRect.cpp

cpp 复制代码
#include "MyRect.h"

bool MYRECT::Sollider(const MYRECT& other)
{
    if(right < other.left || left > other.right || bottom < other.top || top > other.bottom)
        return false;
    return true;
}

bool MYRECT::Set(int x, int y, int w, int h)
{
    left = x;
    top = y;
    right = x + w - 1;
    bottom = y + h -1;
    return true;
}

GameDraw.h

cpp 复制代码
#pragma once
#include <map>
using namespace std;

struct BMP {
	int w, h;
	char _map[100];
};

struct GameDraw {
	int _max_w,_max_h;
	int _w, _h;
	int client[32 * 256];
	char print[(15 * 2 + 1)*16 +1];

	char _ts[128];
	int _tslen;

	int ww = 70, wh = 16;
	int cx = 0, cy = 0, cw = 15, ch = 16;

	map<const char*, BMP> bmp_map;


	void init();//初始化各个数据
	bool SetTs(const char* ts);//设置图素
	bool SetSize(int w, int h);//设置窗口大小
	void Begin();//把窗口大小中的client清零
	void Draw(const char* key,int x,int y);//给client 编码画图
	void End();//把client中的数据显示到窗口上

	bool AddBmp(const char* key,BMP bmp);
};

GameDraw.cpp

cpp 复制代码
#include "GameDraw.h"
#include <iostream>
#include <map>

void GameDraw::init()
{
    _max_w = 256;
    _max_h = 32;
    _ts[0] = "  "[0];
    _ts[1] = "  "[1];
    _tslen = 0;
}

bool GameDraw::SetTs(const char* ts)
{
    if (ts == nullptr) {
        return false;
    }
    int i = 0;
    while (1) {
        if (ts[i] == '\0' || ts[i + 1] == '\0') {
            break;
        }
        _tslen++;
        _ts[_tslen * 2] = ts[i++];
        _ts[_tslen * 2 + 1] = ts[i++];
    }
    return true;
}

bool GameDraw::SetSize(int w, int h)
{
    if (w<1 || h<1 || w> _max_w || h> _max_h) {
        return false;
    }
    _w = w;
    _h = h;
    return true;
}

void GameDraw::Begin()
{
    for (int i = 0; i < _h; i++) {
        for (int j = 0; j < _w; j++) {
            client[i * _w + j] =  0;
        }
    }
}

void GameDraw::Draw(const char* key, int x, int y)
{
    ////第一个 左上角的定位点在地图中就行,其他的出界就不画
    //
    //for (int i = 0; i < h; i++) {
    //    for (int j = 0; j < w; j++) {
    //        if (x >= 0 && x < _w && y >= 0 && y < _h) {
    //            client[y * _w + x] = tsi;
    //            x++;
    //        }
    //    }
    //    y++;
    //    x -= w;
    //}

    if (key == nullptr)
        return;

    map<const char*, BMP>::iterator it;
    it = bmp_map.find(key);
    if (it == bmp_map.end())
        return;

    BMP bmp = it->second;
    for (int i = 0; i < bmp.h; i++) {
        for (int j = 0; j < bmp.w; j++) {
            
            if (bmp._map[j + i * bmp.w] != 0)
                client[y * _w + x] = bmp._map[j + i * bmp.w];
            x++;
        }
        y++;
        x -= bmp.w;
    }
}

void GameDraw::End()
{
    
    int pos = cx + cy * _w;
    int size = 0;
    for (int i = 0; i < ch; i++) {
        for (int j = 0; j < cw; j++) {
            if (client[pos + i * _w + j] == 0) {
                print[size++] = _ts[client[pos + i * _w + j] ];
            }
            else {
                print[size++] = _ts[client[pos + i * _w + j] * 2];
                print[size++] = _ts[client[pos + i * _w + j] * 2 + 1];
            }
            
        }
        print[size++] = '\n';
    }
    print[size] = 0;
    system("cls");
    std::cout << print;
}

bool GameDraw::AddBmp(const char* key, BMP bmp)
{
    if (key == nullptr) 
        return false;
    
    map<const char*, BMP>::iterator it;
    it = bmp_map.find(key);

    if (it == bmp_map.end()) {
        bmp_map.insert(pair<const char*, BMP>(key, bmp));
        return true;
    }
    else
        return true;
}

源.cpp

cpp 复制代码
#include <iostream>
#include"GameDraw.h"
#include<windows.h>

using namespace std;

struct OBJ {
	int  x, y;
	/*int tsi;*/
	const char* key;
};

void main() {
	GameDraw gd;

	OBJ hero = {0,0,"tank"};
	{
		BMP bmp_temp;
		bmp_temp.w = 3;
		bmp_temp.h = 3;
		int temp_map[9] = {
			0,2,0,
			5,4,5,
			5,0,5,
		};
		for (int i = 0; i < 9; i++) {
			bmp_temp._map[i] = temp_map[i];
		}
		gd.AddBmp("tank", bmp_temp);
	}

	{
		BMP bmp_temp;
		bmp_temp.w = 4;
		bmp_temp.h = 5;
		int temp_map[20] = {
			5,5,5,5,
			5,5,5,5,
			0,5,5,0,
			0,5,5,0,
			0,5,5,0,
		};
		for (int i = 0; i < 20; i++) {
			bmp_temp._map[i] = temp_map[i];
		}
		gd.AddBmp("pipe", bmp_temp);
	}

	

	/*OBJ hero = { 0,0,1,1,3 };
	OBJ ground = { 0,15,70,1,5 };
	OBJ brick1 = { 11,5,4,2,5 };
	OBJ brick2 = { 24,6,4,9,5 };*/



	

	while (1) {
		gd.init();
	
		gd.SetSize(70,16);
		gd.Begin();
		gd.SetTs("〓▲★●■");
		gd.Draw("tank",hero.x,hero.y);
		for (int i = 1; i <= 3; i++) {
			gd.Draw("pipe",i*15,11);
		}
		/*gd.Draw(hero.x, hero.y, hero.w, hero.h, hero.tsi);

		gd.Draw(ground.x, ground.y, ground.w, ground.h, ground.tsi);
		gd.Draw(brick1.x, brick1.y, brick1.w, brick1.h, brick1.tsi);
		gd.Draw(brick2.x, brick2.y, brick2.w, brick2.h, brick2.tsi);*/

		Sleep(30);
		gd.End();

		if (GetAsyncKeyState('W')) {
			hero.y -= 1;
		}
		if (GetAsyncKeyState('S')) {
			hero.y += 1;
		}
		if (GetAsyncKeyState('A')) {
			hero.x -= 1;
		}
		if (GetAsyncKeyState('D')) {
			hero.x += 1;
		}

		

		//卷轴

		gd.cx = hero.x - gd.cw/2;
		gd.cy = hero.y - gd.ch/2;
		if (gd.cx < 0) gd.cx = 0;
		if (gd.cy < 0) gd.cy = 0;
		if (gd.cx + gd.cw > gd.ww) gd.cx = gd.ww - gd.cw;
		if (gd.cy + gd.ch > gd.wh) gd.cy = gd.wh - gd.ch;
	}
	Sleep(30);
}
相关推荐
电力程序小学童15 小时前
【复现】一种基于价格弹性矩阵的居民峰谷分时电价激励策略【需求响应】
matlab·矩阵·需求响应·负荷·峰谷电价
lovod17 小时前
【视觉SLAM十四讲】视觉里程计 1
人工智能·线性代数·计算机视觉·矩阵·机器人
却道天凉_好个秋21 小时前
深度学习(十三):向量化与矩阵化
人工智能·深度学习·矩阵·向量化
MMjeaty1 天前
特殊矩阵的压缩存储
算法·矩阵
MoRanzhi12032 天前
基于 SciPy 的矩阵运算与线性代数应用详解
人工智能·python·线性代数·算法·数学建模·矩阵·scipy
优秘智能UMI3 天前
UMI企业智脑智能营销:多平台视频矩阵引领营销新潮流
大数据·运维·人工智能·ai·矩阵·aigc
智者知已应修善业3 天前
【C++无数组矩阵对角线平均值保留2位小数】2022-11-18
c语言·c++·经验分享·笔记·算法·矩阵
MoRanzhi12033 天前
12. NumPy 数据分析与图像处理入门
大数据·图像处理·人工智能·python·矩阵·数据分析·numpy
贝塔实验室4 天前
ADMM 算法的基本概念
算法·数学建模·设计模式·矩阵·动态规划·软件构建·傅立叶分析