开发日志
/*
2022.3.3
1.实现玩家的奔跑
2.实现玩家的跳跃
3.优化帧等待
4.实现小乌龟随机出现
5.结构体封装
*/
今日代码
运用池的思想,需要障碍物时从池中调取
//它用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型,本质上是整数
//typedef enum则是用来定义一个数据类型,那么该类型的变量值只能在enum定义的范围内取
typedef enum {
//瓜 0
MELON,
//华强 1
HUAQIANG,
//四种柱子
//需要改变障碍物出现频率,取余
PILLAR1,
PILLAR2,
PILLAR3,
PILLAR4,
//边界,判断有几种枚举值 6
OBSTACLE_TYPE_COUNT
}obstacle_type;
//可变二维数组,与下面那个二维数组等价
//存放所有障碍物的各个图片
vector<vector<IMAGE>>obstacleImgs;
//内存占用较小(还不理解
// 还可以用C++的容器特性,可变数组继续优化,加头文件
//IMAGE obstacleImgs[3][12];
//暂时不理解typedef
typedef struct obstacle {
//障碍物类型
obstacle_type type;
//当前时刻显示的图片的序号
int imgIndex;
//障碍物的坐标
int x, y;
//速度
int speed;
//杀伤力
int power;
//是否在窗口
bool exist;
//占用更多内存
//IMAGE img[12];
}obstacle_t;
//障碍物池
obstacle_t obstacles[OBSTACLE_COUNT];
初始化
//加载人物奔跑的图片帧素材
for (int i = 0; i < 12; i++) {
//"res/hero1~12.png"
sprintf(name, "res/hero%d.png", i + 1);
loadimage(&imgPlayer[i], name);
}
//玩家初始位置
//getwidth获取图片宽度函数
playerX = WIN_WIDTH * 0.5 - imgPlayer[0].getwidth() * 0.5;
playerY = 375 - imgPlayer[0].getheight();
playerIndex = 0;
//跳跃状态
startJump = false;
//跳跃最大高度
jumpHeightMax = playerY - 300;
//跳跃初速度
jumpSpeed = -20;
//刷新画面
update = true;
//加载瓜素材
/*loadimage(&imgMelon, "res/t1.png");
melonExist = false;
melonY = 375 - imgMelon.getheight();*/
IMAGE imgMelon;
vector<IMAGE>imgMelonArray;
for (int i = 0; i < 6; i++) {
sprintf(name, "res/t%d.png", i + 1);
loadimage(&imgMelon, name);
//在数组的尾部追加
imgMelonArray.push_back(imgMelon);
}
//存入二维数组
obstacleImgs.push_back(imgMelonArray);
//加载华强素材
IMAGE imgHuaqiang;
vector<IMAGE>imgHuaqiangArray;
for (int i = 0; i < 8; i++) {
sprintf(name, "res/p%d.png", i + 1);
loadimage(&imgHuaqiang, name, 210, 210, true);
imgHuaqiangArray.push_back(imgHuaqiang);
}
obstacleImgs.push_back(imgHuaqiangArray);
//初始化障碍物池
for (int i = 0; i < OBSTACLE_COUNT; i++) {
obstacles[i].exist = false;
}
//加载下蹲素材
for (int i = 0; i < 2; i++) {
sprintf(name, "res/d%d.png", i + 1);
loadimage(&imgPlayerDown[i], name);
}
startDown = false;
//加载柱子素材
IMAGE imgPillar;
//vector<IMAGE>imgPillarArray;错的
for (int i = 0; i < 4; i++) {
//放在外面会导致柱子图片按帧动,就是二维数组按列储存了,在里面是按行
vector<IMAGE>imgPillarArray;
sprintf(name, "res/h%d.png", i + 1);
//对图片进行缩放
loadimage(&imgPillar, name, 63, 260, true);
imgPillarArray.push_back(imgPillar);
obstacleImgs.push_back(imgPillarArray);
}
}
//创建障碍物
void createObstacle() {
int i;
//找一个没有用过的
for (i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist == false){
break;
}
}
//没找到
if (i >= OBSTACLE_COUNT) {
return;
}
obstacles[i].exist = true;
obstacles[i].imgIndex = 0;
//type不是整型
obstacles[i].type = (obstacle_type)(rand() % 3);
//优化柱子出现频率,使柱子自为一类
if (obstacles[i].type == PILLAR1) {
//注意数据类型
obstacles[i].type = (obstacle_type)((int)obstacles[i].type + rand() % 4);
}
obstacles[i].x = WIN_WIDTH;
obstacles[i].y = 375 - obstacleImgs[obstacles[i].type][0].getheight();
if (obstacles[i].type == MELON) {
obstacles[i].speed = 0;
obstacles[i].power = 5;
}
else if (obstacles[i].type == HUAQIANG) {
obstacles[i].speed = 4;
obstacles[i].power = 20;
}
//同类型
else if (obstacles[i].type >= PILLAR1&& obstacles[i].type <= PILLAR4) {
obstacles[i].speed = 0;
obstacles[i].power = 20;
obstacles[i].y = 0;
}
玩家动作实现
//开关打开,实现跳跃
if (startJump) {
if (playerY < jumpHeightMax) {
jumpSpeed = 0;
}
//仿重力
playerY += (jumpSpeed++);
//大于等于,不然第一次起跳会偏移
if (playerY >= 375 - imgPlayer[0].getheight()) {
startJump = false;
//回归初始态
jumpSpeed = -20;
}
}
else if (startDown) {
static int count = 0;
int delays[2] = { 4, 10 };
count++;
if (count >= delays[playerIndex]) {
count = 0;
playerIndex++;
if (playerIndex >= 2) {
playerIndex = 0;
startDown = false;
}
}
}
//不跳不蹲才奔跑
else {
//注意别写i=i++这种傻代码了!!!
playerIndex = (++playerIndex) % 12;
}
//静态变量,函数调用完之后不会被销毁,下次调用值不变
static int frameCount = 0;
//生成障碍物频率
static int enemyFre = 100;
//每100帧生成一只障碍物
frameCount++;
if (frameCount > enemyFre) {
//计数器清零
frameCount = 0;
//if (!melonExist) {
// melonExist = true;
// melonX = WIN_WIDTH;
// //每200~500帧生成一只 200+0...300
//}
enemyFre = 50 + rand() % 100;
//用来刷障碍物,障碍物刷出来就会往左移动
createObstacle();
}
//更新所有障碍物坐标
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist) {
obstacles[i].x -= (obstacles[i].speed + bgSpeed[2]);
if (obstacles[i].x < -obstacleImgs[obstacles[i].type][0].getwidth() * 2) {
obstacles[i].exist = false;
}
//图片索引
//二维数组size()第几行有几个元素
int len = obstacleImgs[obstacles[i].type].size();
obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
}
}
}
//人物奔跑与下蹲
void playerRun() {
if (!startDown) {
putimagePNG2(playerX,playerY,&imgPlayer[playerIndex]);
}
else {
int y = 375 - imgPlayerDown[playerIndex].getheight();
putimagePNG2(playerX, y, &imgPlayerDown[playerIndex]);
}
//人物跳跃
void playerJumpSwitch() {
//需要一个启动跳跃的开关,跳跃不能在一帧内完成,开关触发后,main函数循环开始跳跃
startJump = true;
update = true;
}
//人物下蹲
void playerDownSwitch() {
startDown = true;
update = true;
playerIndex = 0;
}
用户按键输入
//处理用户按键的输入
void keyEvent() {
//scanf会阻塞程序的执行
char ch;
//如果有按键按下,kbhit()返回为真
if (_kbhit()) {
//_getch()不需要按下回车即可直接读取
ch=_getch();
if (ch == 'k'){
playerJumpSwitch();
}
else if (ch == 'j') {
playerDownSwitch();
}
}
}
渲染障碍物
//渲染障碍物
void updateEnemy() {
for (int i = 0; i < OBSTACLE_COUNT; i++) {
if (obstacles[i].exist) {
putimagePNG2(obstacles[i].x, obstacles[i].y, WIN_WIDTH, &obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
}
}
}
暂无演示效果
|