当前位置: 首页 > news >正文

卷轴 缓冲绘制 超级玛丽demo5

难度预警!

卷轴的概念

在游戏开发中,卷轴(Scrolling)指游戏画面随玩家操作或时间推移而横向或纵向移动的视觉效果,如同展开画卷一般。

 相对坐标和绝对坐标

我们制作游戏的时候,世界是很大的,窗口只能显示出一小部分。所以就有了卷轴。

我们始终把 要操作的英雄放在窗口的中心。

英雄的坐标为x,y   窗口的大小为 w,h

我们默认 窗口的左上角坐标为 窗口的坐标

得到窗口坐标(cx,cy)为: x-w/2 , y- h/2

有了窗口之后,假如我们的世界有地球这么大,我们之前进行碰撞检测是全世界检测,其实我们只用检测英雄周围的范围就可以了。

 

这个超级玛丽

窗口  高16格  宽15格

世界  高16格  宽70格

定比例尺 最小的一格方便计算我们定为50像素*50像素

一共得到 3500 * 750 的世界大小

在(11,5)  w=4 h=2的障碍物

在(24,6)w=4 h=9的障碍物

缓冲绘制

我们之前是一个字符 一个字符 cout 打印出来的,这次直接把窗口内所有东西 都放在一个字符串中,一次性打印整个窗口的内容,就完成了缓冲绘制。

为了防止画面闪烁,我们直接在清空控制台后 马上打印整个字符串,闪烁的问题 就基本解决了。

(但是还是会有闪的一瞬间,目前还无法解决,后面我们会学习二次缓冲但是文字无法使用)

理论部分很简单 下面我们来实践一下。

超级玛丽demo5

各个函数的目录

我们上一节的末尾讲了 模块绘制但是 没有用代码来实现。

模块绘制

这里我们从draw函数下手 把模块绘制先改一下

在之前 我们的draw 函数的功能是 给世界中的方块 赋值为图素的编码

这里我们改为 模块绘制

给出左上角坐标 (x,y) 还有 宽w 高h  全部绘制出来一个整体

void GameDraw::Draw(int x, int y, int w,int h,int tsi)
{//第一个 左上角的定位点在地图中就行,其他的出界就不画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;}
}

卷轴

我们约定

h_max , w_max  是整个程序 给你的空间

_h  , _w  是世界的大小

h, w 是窗口大小

在头文件里面加几个量,还有print 我们的缓冲绘制区。

GameDraw.h

#pragma once
struct GameDraw {int _max_w,_max_h;int _w, _h;int client[32 * 256];char print[256];char _ts[128];int _tslen;int ww = 70, wh = 16;int cx = 0, cy = 0, cw = 15, ch = 16;void init();//初始化各个数据bool SetTs(const char* ts);//设置图素bool SetSize(int w, int h);//设置窗口大小void Begin();//把窗口大小中的client清零void Draw(int x, int y, int w,int h,int tsi);//给client 编码画图void End();//把client中的数据显示到窗口上
};

GameDraw.h

#pragma once
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;void init();//初始化各个数据bool SetTs(const char* ts);//设置图素bool SetSize(int w, int h);//设置窗口大小void Begin();//把窗口大小中的client清零void Draw(int x, int y, int w,int h,int tsi);//给client 编码画图void End();//把client中的数据显示到窗口上
};

gamedraw.cpp

#include "GameDraw.h"
#include <iostream>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(int x, int y, int w,int h,int tsi)
{//第一个 左上角的定位点在地图中就行,其他的出界就不画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;}
}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++) {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;
}

源.cpp

#include <iostream>
#include"GameDraw.h"
#include<windows.h>using namespace std;struct OBJ {int x, y, w, h;int tsi;
};void main() {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 };GameDraw gd;while (1) {gd.init();gd.SetSize(70,16);gd.Begin();gd.SetTs("〓▲★●■");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;}}

http://www.dtcms.com/a/410372.html

相关文章:

  • 1.9 IP地址和Mac地址
  • C# WinForms的入门级画板实现
  • 云南网站建设方案简述营销型网站开发流程
  • 随时随地学算法:Hello-Algo与cpolar的远程学习方案
  • App 上架全流程指南,iOS 应用发布步骤、ipa 文件上传工具、TestFlight 分发与 App Store 审核经验分享
  • 网站建设公司推荐常德网站开发服务
  • 全球知名的Java Web开发平台Vaadin上线慧都网
  • 【QT】高级主题
  • 详细对比web请求post和put的区别
  • dedecms 营销网站模板免费下载专业设计网址青岛网站开发
  • 正在招 | 2025.9 福建 IT 相关岗位招聘信息
  • 树莓派4B+ubuntu20.04:不插显示器能不能正常开机?
  • 开发大型网站的最主流语言上海seo网站优化_搜索引擎排名_优化型企业网站建设_锦鱼网络
  • 从远程控制到AI赋能:ToDesk如何重塑未来办公新生态?
  • Python爬虫进阶:突破反爬机制(UA伪装+代理池+验证码识别)
  • 华为发布开源超节点架构,以开放战略叩响AI算力生态变局
  • 从格伦的角度理解信息哲学
  • 网站建设分金手指专业三十WordPress 多用户数据
  • obsidian git操作及踩坑记录:ssh秘钥设置以及推送到多个远程仓库
  • 【Linux】网络部分——网络基础(Socket 编程预备)
  • 【音频】SIP服务器Yate搭建
  • 贵阳网站建设宏思锐达网站挂服务器后图片不显示
  • @tanstack/react-query:React 服务器状态管理与数据同步解决方案
  • RCNN系列边界框回归损失函数
  • 郑州专业网站制作建设python基础教程雪峰
  • Go基础:文件与文件夹操作详解
  • 鸿蒙:侧边栏显示与隐藏
  • 【开题答辩实录分享】以《基于爬虫的娱乐新闻采集系统设计与实现》为例进行答辩实录分享
  • BMAD方法论与自动化工具的协同演进:重塑Go语言微服务的技术债务
  • 月匣 - 百度推出的AI情感陪伴与剧情互动应用