首页 > 其他分享 >基于EasyX和Raylib的坚持100秒

基于EasyX和Raylib的坚持100秒

时间:2023-01-25 20:33:10浏览次数:58  
标签:float rocket Raylib void EasyX texture im 100 ufo

EasyX

// 根据《C和C++游戏趣味编程》第12章 坚持100秒 写出

#include <graphics.h>
#include <conio.h> // _kbhit()
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "EasyXPng.h"

// 引用 Windows Multimedia API
#pragma comment(lib, "Winmm.lib")

// global variables
#define WIDTH 560
#define HEIGHT 800

IMAGE im_bk;
IMAGE im_rocket;
IMAGE im_blowup;
IMAGE im_bullet;

void playMusicOnce(char filename[80])
{
    char cmdString[50] = { 0 };
    sprintf(cmdString, "open %s alias tmpmusic", filename);
    mciSendString("close tmpmusic", NULL, 0, NULL); // 先关闭前一次的音乐
    mciSendString(cmdString, NULL, 0, NULL); // 打开这次的音乐
    mciSendString("play tmpmusic", NULL, 0, NULL); // 仅播放一次
}

// 火箭
class Rocket
{
public:
	IMAGE im_rocket;
	IMAGE im_blowup;
	float x, y;
	float width;
	float height;
	int liveSecond; // 存活了多长时间
	int life; // 几条命

	void draw()
	{
		if (life > 0)
		{
			putimagePng(x - width / 2, y - height / 2, &im_rocket);
		}
		else
		{
			putimagePng(x - width / 2, y - height / 2, &im_blowup);
		}

		// 窗口左上角显示 life 个火箭图标
		for (int i = 0; i < life; i++)
		{
            // 注: 如果去掉 ofs, 看起来结果应该一样,但实际运行时子弹不会出现,推测是编译器优化导致结果差异。。
            int ofs = 0;
			putimagePng(ofs + i * width * 0.9, ofs, &im_rocket);
		}

		char s[20] = { 0 };
		setbkmode(TRANSPARENT);
		sprintf(s, "%d秒", liveSecond);
		settextcolor(WHITE);
		settextstyle(40, 0, _T("黑体"));
		outtextxy(WIDTH * 0.85, 20, s);
	}

	void update(float mx, float my)
	{
		x = mx;
		y = my;
	}

	void updateWhenLifeLost()
	{
		if (life > 0)
		{
            playMusicOnce("explode.mp3");
			life--;
            if (life == 0)
            {
                mciSendString("close bkmusic", NULL, 0, NULL);
            }
		}
	}
};

// 子弹
class Bullet
{
public:
	IMAGE image;
	float x, y; // coordinate
	float vx, vy; // velocity
	float radius;

	void draw()
	{
		putimagePng(x - radius, y - radius, &image);
	}

	void update()
	{
		x += vx;
		y += vy;
		if (x <= 0 || x >= WIDTH)
		{
			vx = -vx;
		}
		if (y <= 0 || y >= HEIGHT)
		{
			vy = -vy;
		}
	}

	// 判断子弹是否和火箭碰撞
	bool isCollideRocket(Rocket rocket) const
	{
		float distanec_x = fabs(rocket.x - x);
		float distance_y = fabs(rocket.y - y);
		if (distanec_x < rocket.width / 2 && distance_y < rocket.height / 2)
		{
			return true;
		}
		return false;
	}
};

// 飞碟
class SmartUFO : public Bullet
{
public:
	void updateVelForTarget(Rocket targetRocket)
	{
		float scalar = rand() / double(RAND_MAX) + 1;
		if (targetRocket.x > x)
		{
			vx = scalar;
		}
		else if (targetRocket.x < x)
		{
			vx = -scalar;
		}

		if (targetRocket.y > y)
		{
			vy = scalar;
		}
		else if (targetRocket.y < y)
		{
			vy = -scalar;
		}
	}
};

int bulletNum = 0;
#define MaxBulletNum 20
Bullet bullet[MaxBulletNum];

Rocket rocket;

IMAGE im_UFO;
SmartUFO ufo;

void startup()
{
    mciSendString(_T("open game_music.mp3 alias bkmusic"), NULL, 0, NULL); // 打开背景音乐
    mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL); // 循环播放
	loadimage(&im_bk, "background.png");
	loadimage(&im_rocket, "rocket.png");
	loadimage(&im_blowup, "blowup.png");
	loadimage(&im_bullet, "bullet.png");
	loadimage(&im_UFO, "ufo.png");

	rocket.im_rocket = im_rocket;
	rocket.im_blowup = im_blowup;
	rocket.width = im_rocket.getwidth();
	rocket.height = im_rocket.getheight();
	rocket.life = 5;

	ufo.x = WIDTH / 2;
	ufo.y = 10;
	ufo.image = im_UFO;
	ufo.radius = im_UFO.getwidth() / 2;
	ufo.updateVelForTarget(rocket);

	initgraph(WIDTH, HEIGHT, SHOWCONSOLE);
	BeginBatchDraw();
}

// 精确延时函数
void sleep(DWORD ms)
{
	static DWORD oldtime = GetTickCount();
	while (GetTickCount() - oldtime < ms)
	{
		Sleep(1);
	}
	oldtime = GetTickCount();
}

void show()
{
	putimage(0, 0, &im_bk); // background image
	for (int i = 0; i < bulletNum; i++)
	{
		bullet[i].draw();
	}
	rocket.draw();
	ufo.draw();
	FlushBatchDraw();
	sleep(10);
}

void updateWithoutInput()
{
	if (rocket.life <= 0)
	{
		return;
	}

	// 每隔2s,新生成一颗子弹
	static int lastSecond = 0;
	static int nowSecond = 0;
	static clock_t start = clock();
	clock_t now = clock();
	nowSecond = (int(now - start) / CLOCKS_PER_SEC);
	rocket.liveSecond = nowSecond;

	if (nowSecond == lastSecond + 1)
	{
		// 时间过了1秒, 更新飞碟速度
		ufo.updateVelForTarget(rocket);

		// 更新飞碟位置和速度
		ufo.update();

		// 如果飞碟和火箭相撞, 则火箭减命, 飞碟回到左上角初始位置
		if (ufo.isCollideRocket(rocket))
		{
			rocket.updateWhenLifeLost();
			ufo.x = 5;
			ufo.y = 5;
		}
	}

	if (bulletNum < MaxBulletNum && nowSecond == lastSecond + 2)
	{
		// printf("bulletNum = %d, MaxBulletNum = %d\n", bulletNum, MaxBulletNum);
		bullet[bulletNum].x = WIDTH / 2;
		bullet[bulletNum].y  = 10;
		float angle = (rand() / double(RAND_MAX) - 0.5) * 0.9 * PI;
		float scalar = 2 * rand() / double(RAND_MAX) + 2;
		bullet[bulletNum].vx = scalar * sin(angle);
		bullet[bulletNum].vy = scalar * cos(angle);
		bullet[bulletNum].image = im_bullet;
		bullet[bulletNum].radius = im_bullet.getwidth() / 2;
		bulletNum++;

		lastSecond = nowSecond;
	}

	for (int i = 0; i < bulletNum; i++)
	{
		bullet[i].update();
		if (bullet[i].isCollideRocket(rocket))
		{
			rocket.updateWhenLifeLost();
			bullet[i].x = 5; // 当前子弹移开, 防止重复碰撞
			bullet[i].y = 5;
			break;
		}
	}
}

void updateWithInput()
{
	if (rocket.life <= 0)
	{
		return;
	}

	MOUSEMSG m;
	while (MouseHit())
	{
		m = GetMouseMsg();
		if (m.uMsg == WM_MOUSEMOVE)
		{
			rocket.update(m.x, m.y);
		}
	}
}

int main()
{
	startup();
	while (1)
	{
		show();
		updateWithoutInput();
		updateWithInput();
	}

	closegraph();

	return 0;
}

基于 Raylib

// 根据《C和C++游戏趣味编程》第12章 坚持100秒 写出

#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include "raylib_helper.hpp"
#include <time.h>
#include <math.h>

// global variables
#define WIDTH 560
#define HEIGHT 800

Texture2D bk_texture;
Texture2D rocket_texture;
Texture2D blowup_texture;
Texture2D bullet_texture;

Music bk_music; // 背景音乐
Music ep_music; // 爆炸声

void playMusicOnce(char filename[80])
{
    StopMusicStream(ep_music);
    ep_music.looping = false;
    PlayMusicStream(ep_music);
}

class Rocket
{
public:
	Texture2D rocket_texture;
	Texture2D blowup_texture;
	float x;
	float y;
	float width;
	float height;
	int liveSecond; // 存活了多长时间
	int life; // 几条命

	void draw()
	{
		if (life > 0)
		{
			DrawTexture(rocket_texture, x - width / 2, y - height / 2, WHITE);
		}
		else
		{
			DrawTexture(blowup_texture, x - width / 2, y - height / 2, WHITE);	
		}

		// 窗口左上角显示 life 个火箭图标
		for (int i = 0; i < life; i++)
		{
			int ofs = 0;
			DrawTexture(rocket_texture, ofs + i * width * 0.9, ofs, WHITE);
		}

		char s[20] = { 0 };
		sprintf(s, "%d s", liveSecond);
		DrawText(s, WIDTH * 0.85, 20, 40, WHITE);
	}

	void update(Vector2 pos)
	{
		x = pos.x;
		y = pos.y;
	}

	void updateWhenLifeLost()
	{
		if (life > 0)
		{
			life--;
            playMusicOnce("explode.mp3");
            
            if (life == 0)
            {
                StopMusicStream(bk_music);
            }
		}
	}
};

class Bullet
{
public:
	Texture2D texture;
	float x, y; // coordinate
	float vx, vy; // velocity
	float radius;

	void draw()
	{
		DrawTexture(texture, x - radius, y - radius, WHITE);
	}

	void update()
	{
		x += vx;
		y += vy;
		if (x <= 0 || x >= WIDTH)
		{
			vx = -vx;
		}
		if (y <= 0 || y >= HEIGHT)
		{
			vy = -vy;
		}
	}

	// 判断子弹是否和火箭碰撞
	bool isCollideRocket(Rocket rocket) const
	{
		float distanec_x = fabs(rocket.x - x);
		float distance_y = fabs(rocket.y - y);
		if (distanec_x < rocket.width / 2 && distance_y < rocket.height / 2)
		{
			return true;
		}
		return false;
	}
};

// 飞碟
class SmartUFO : public Bullet
{
public:
	void updateVelForTarget(Rocket targetRocket)
	{
		float scalar = rand() / double(RAND_MAX) + 1;
		if (targetRocket.x > x)
		{
			vx = scalar;
		}
		else if (targetRocket.x < x)
		{
			vx = -scalar;
		}

		if (targetRocket.y > y)
		{
			vy = scalar;
		}
		else if (targetRocket.y < y)
		{
			vy = -scalar;
		}
	}
};


#define MaxBulletNum 20
Bullet bullet[MaxBulletNum];
int bulletNum = 0;

Rocket rocket;

Texture2D ufo_texture;
SmartUFO ufo;

void startup()
{
    SetConfigFlags(FLAG_MSAA_4X_HINT);  // NOTE: Try to enable MSAA 4X
	InitWindow(WIDTH, HEIGHT, "persist 100 seconds");
    SetTargetFPS(60);

    InitAudioDevice();                  // Initialize audio device

    //bk_music = LoadMusicStream("game_music.mp3");
    char* music_path = "C:/Users/zz/work/cppsober/games/assets/game_music.mp3";
    bk_music = LoadMusicStream(music_path);
    bk_music.looping = true;
    PlayMusicStream(bk_music);

    ep_music = LoadMusicStream("explode.mp3");

	bk_texture = LoadTexture("background.png");
	rocket_texture = LoadTexture("rocket.png");
	blowup_texture = LoadTexture("blowup.png");
	bullet_texture = LoadTexture("bullet.png");
	ufo_texture = LoadTexture("ufo.png");

	rocket.rocket_texture = rocket_texture;
	rocket.blowup_texture = blowup_texture;
	rocket.width = rocket_texture.width;
	rocket.height = rocket_texture.height;
	rocket.life = 5;
	rocket.x = WIDTH / 2;
	rocket.y = HEIGHT / 2;

	ufo.x = WIDTH / 2;
	ufo.y = 10;
	ufo.texture = ufo_texture;
	ufo.radius = ufo_texture.width / 2;
	ufo.updateVelForTarget(rocket);
}

void show()
{
	BeginDrawing();
	{
	    DrawTexture(bk_texture, WIDTH/2 - bk_texture.width/2, HEIGHT/2 - bk_texture.height/2, WHITE);
		for (int i = 0; i < bulletNum; i++)
		{
			bullet[i].draw();
		}
		rocket.draw();
		ufo.draw();
	}
	EndDrawing();	
}

void updateWithoutInput()
{
	if (rocket.life <= 0)
	{
		return;
	}

	// 每隔2s,新生成一颗子弹
	static int lastSecond = 0;
	static int nowSecond = 0;
	static clock_t start = clock();
	clock_t now = clock();
	nowSecond = (int(now - start) / CLOCKS_PER_SEC);
	rocket.liveSecond = nowSecond;

	if (nowSecond == lastSecond + 1)
	{
		// 时间过了1秒, 更新飞碟速度
		ufo.updateVelForTarget(rocket);

		// 更新飞碟位置和速度
		ufo.update();

		// 如果飞碟和火箭相撞, 则火箭减命, 飞碟回到左上角初始位置
		if (ufo.isCollideRocket(rocket))
		{
			rocket.updateWhenLifeLost();
			ufo.x = 5;
			ufo.y = 5;
		}
	}

	if (bulletNum < MaxBulletNum && nowSecond == lastSecond + 2)
	{
		lastSecond = nowSecond;
		bullet[bulletNum].x = WIDTH / 2;
		bullet[bulletNum].y  = 10;
		float angle = (rand() / double(RAND_MAX) - 0.5) * 0.9 * PI;
		float scalar = 2 * rand() / double(RAND_MAX) + 2;
		bullet[bulletNum].vx = scalar * sin(angle);
		bullet[bulletNum].vy = scalar * cos(angle);
		bullet[bulletNum].texture = bullet_texture;
		bullet[bulletNum].radius = bullet_texture.width / 2;
		bulletNum++;
	}

	for (int i = 0; i < bulletNum; i++)
	{
		bullet[i].update();
		if (bullet[i].isCollideRocket(rocket))
		{
			rocket.updateWhenLifeLost();
			bullet[i].x = 5; // 当前子弹移开, 防止重复碰撞
			bullet[i].y = 5;
			break;
		}
	}
}

void updateWithInput()
{
	if (rocket.life <= 0)
	{
		return;
	}

	Vector2 pos = GetMousePosition();
	rocket.update(pos);
}

int main()
{
    startup();

    while (!WindowShouldClose())
    {
        UpdateMusicStream(bk_music);
        UpdateMusicStream(ep_music);
    	updateWithoutInput();
    	updateWithInput();
        show();
    }

    UnloadTexture(bk_texture);
    UnloadTexture(rocket_texture);
    UnloadTexture(blowup_texture);
    UnloadTexture(bullet_texture);

    CloseWindow();

    return 0;
}

标签:float,rocket,Raylib,void,EasyX,texture,im,100,ufo
From: https://www.cnblogs.com/zjutzz/p/17067252.html

相关文章

  • 基于EasyX和Raylib的字符雨
    思路按如下顺序尝试:绘制一个字符下落绘制4个字符(一列)的下落绘制20个字符(一列)的下落,并封装其位置更新、绘制的过程为Rain类的成员函数绘制多个雨滴每个雨滴在更新......
  • 基于EasyX和Raylib的贪吃蛇
    基于EasyX//根据《C和C++游戏趣味编程》第七章贪吃蛇写出#include<graphics.h>#include<conio.h>//_kbhit()#include<stdio.h>#include<stdlib.h>//全......
  • POJ1002 487-3279
    描述商人们喜欢使用方便记忆的电话号码。让号码方便记忆的一种方法是让它拼成好记的单词或词组。例如,你可以叫Waterloo大学TUT-GLOP。有时候只有数字的一部分参与拼写。当......
  • 程序:计算1/1-1/2+1/3......-1/100
    #include<stdio.h>intmain(){inti=1;intflag=1;doublesum=0;for(i=1;i<=100;i++){sum+=flag*(1.0/i);flag=-flag;}prin......
  • 程序:运用函数找出100至200的素数,并数出个数
    #include<stdio.h>intif_a_is_prime(intd){intc=2;for(c=2;c<d;c++){if(d%c==0){return0;}}return1;}intmain(){inta=......
  • 程序:在1——100中寻找能被三整除的数字
    #include<stdio.h>intmain(){inti=1;for(i=1;i<101;i++){if(i%3==0){printf("%d\n",i);}}return0;}......
  • P1008 [NOIP1998 普及组] 三连击
    置顶题解暴力,加简化的判断,数学原理,2个集合内所有数相加相乘结果一样,2个集合的内容一样(没错我自己编得,灵感并不是我自己的,感谢帮我的大大)置顶的题解中的数学原理应该是......
  • EasyX——概要
    EasyX之绘图(配置与显示图片)EasyX之鼠标   ......
  • 洛谷 P1002 [NOIP2002 普及组] 过河卒
    P1002[NOIP2002普及组]过河卒#include<stdio.h>#include<stdlib.h>#include<string.h>intmain(){intHorse_y[8]={2,1,-1,-2,-2,-1,1,2};......
  • 100w人在线的 弹幕 系统,是怎么架构的?
    文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面......