Let's make 16 games in C++(九):Outrun

1、准备游戏需要的背景

 

2、首先渲染一个方框

#include<SFML/Graphics.hpp>
#include<time.h>

using namespace sf;

int width = 1024;
int height = 768;

void drawQuad(RenderWindow &w, Color c, int x1, int y1, int w1, int x2, int y2, int w2)
{
	ConvexShape shape(4);
	shape.setFillColor(c);
	shape.setPoint(0, Vector2f(x1 - w1, y1));
	shape.setPoint(1, Vector2f(x2 - w2, y2));
	shape.setPoint(2, Vector2f(x2 + w2, y2));
	shape.setPoint(3, Vector2f(x1 + w1, y1));
	w.draw(shape);
}
int main()
{
	RenderWindow app(VideoMode(width, height), "Outrun!");
	app.setFramerateLimit(60);

	while (app.isOpen())
	{
		Event e;
		while (app.pollEvent(e))
		{
			if (e.type == Event::Closed)
			{
				app.close();
			}
		}
		app.clear();
		drawQuad(app, Color::Green, 500, 500, 200, 500, 300, 100);
		app.display();	
	}


	return 0;
}

3、同理添加树和房子

#include<SFML/Graphics.hpp>

using namespace sf;

int width = 1024;
int height = 768;

int roadW = 2000;
int segL = 200;//segment length
float camD = 0.84;//camera depth

struct Line
{
	float x;
	float y;
	float z;//3d center of line
	float X;
	float Y;
	float W;//screen coord
	float scale;
	float curve;
	float spriteX;
	float clip;
	Sprite sprite;

	Line()
	{
		spriteX=curve=x = y = z = 0;
	}

	void project(int camX, int camY, int camZ)
	{
		scale = camD / (z - camZ);
		X = (1 + scale * (x - camX)) * width / 2;
		Y = (1 - scale * (y - camY)) * height / 2;
		W = scale * roadW * width / 2;
	}
	void drawSprite(RenderWindow &app)
	{
		Sprite s = sprite;
		int w = s.getTextureRect().width;
		int h = s.getTextureRect().height;

		float destX = X + scale * spriteX * width / 2;
		float destY = Y + 4;
		float destW = w * W / 266;
		float destH = h * W / 266;

		destX += destW * spriteX; //offsetX
		destY += destH * (-1);    //offsetY

		float clipH = destY + destH - clip;
		if (clipH < 0) clipH = 0;

		if (clipH >= destH) return;
		s.setTextureRect(IntRect(0, 0, w, h - h * clipH / destH));
		s.setScale(destW / w, destH / h);
		s.setPosition(destX, destY);
		app.draw(s);
	}
};


void drawQuad(RenderWindow &w, Color c, int x1, int y1, int w1, int x2, int y2, int w2)
{
	ConvexShape shape(4);
	shape.setFillColor(c);
	shape.setPoint(0, Vector2f(x1 - w1, y1));
	shape.setPoint(1, Vector2f(x2 - w2, y2));
	shape.setPoint(2, Vector2f(x2 + w2, y2));
	shape.setPoint(3, Vector2f(x1 + w1, y1));
	w.draw(shape);
}


int main()
{
	RenderWindow app(VideoMode(width, height), "Outrun!");
	app.setFramerateLimit(60);

	Texture t[50];
	Sprite object[50];
	for (int i = 1; i <= 7; i++)
	{
		t[i].loadFromFile("./Resources/images/" + std::to_string(i) + ".png");
		t[i].setSmooth(true);
		object[i].setTexture(t[i]);
	}

	Texture bg;
	bg.loadFromFile("./Resources/images/bg.png");
	bg.setRepeated(true);
	Sprite sBackground(bg);
	sBackground.setTextureRect(IntRect(0, 0, 5000, 411));
	sBackground.setPosition(-2000, 0);

	std::vector<Line> lines;
	for (int i = 0; i < 1600; i++)
	{
		Line line;
		line.z = i * segL;

		if (i > 300 && i < 700) line.curve = 0.5;
		if (i > 1100) line.curve = -0.7;

		if (i < 300 && i % 20 == 0) { line.spriteX = -2.5; line.sprite = object[5]; }
		if (i % 17 == 0) { line.spriteX = 2.0; line.sprite = object[6]; }
		if (i > 300 && i % 20 == 0) { line.spriteX = -0.7; line.sprite = object[4]; }
		if (i > 800 && i % 20 == 0) { line.spriteX = -1.2; line.sprite = object[1]; }
		if (i == 400) { line.spriteX = -1.2; line.sprite = object[7]; }

		if (i > 750) line.y = sin(i / 30.0) * 1500;

		lines.push_back(line);
	}

	int N = lines.size();
	float playerX = 0;
	int pos = 0;
	int H = 1500;

	while (app.isOpen())
	{
		Event e;
		while (app.pollEvent(e))
		{
			if (e.type == Event::Closed)
			{
				app.close();
			}
		}
		app.clear();

		int speed = 0;

		if (Keyboard::isKeyPressed(Keyboard::Right)) playerX += 0.1;
		if (Keyboard::isKeyPressed(Keyboard::Left)) playerX -= 0.1;
		if (Keyboard::isKeyPressed(Keyboard::Up)) speed = 200;
		if (Keyboard::isKeyPressed(Keyboard::Down)) speed = -200;
		if (Keyboard::isKeyPressed(Keyboard::Tab)) speed *= 3;
		if (Keyboard::isKeyPressed(Keyboard::W)) H += 100;
		if (Keyboard::isKeyPressed(Keyboard::S)) H -= 100;

		pos += speed;
		while (pos >= N * segL) pos -= N * segL;
		while (pos < 0) pos += N * segL;

		app.clear(Color(105, 205, 4));
		app.draw(sBackground);
		int startPos = pos / segL;
		int camH = lines[startPos].y + H;
		if (speed > 0) sBackground.move(-lines[startPos].curve * 2, 0);
		if (speed < 0) sBackground.move(lines[startPos].curve * 2, 0);

		int maxy = height;
		float x = 0, dx = 0;

		///draw road
		for (int n = startPos; n < startPos + 300; n++)
		{
			Line &l = lines[n%N];
			l.project(playerX*roadW - x, camH, startPos*segL - (n >= N ? N * segL : 0));
			x += dx;
			dx += l.curve;

			l.clip = maxy;
			if (l.Y >= maxy) continue;
			maxy = l.Y;

			Color grass = (n / 3) % 2 ? Color(16, 200, 16) : Color(0, 154, 0);
			Color rumble = (n / 3) % 2 ? Color(255, 255, 255) : Color(0, 0, 0);
			Color road = (n / 3) % 2 ? Color(107, 107, 107) : Color(105, 105, 105);

			Line p = lines[(n - 1) % N]; //previous line

			drawQuad(app, grass, 0, p.Y, width, 0, l.Y, width);
			drawQuad(app, rumble, p.X, p.Y, p.W*1.2, l.X, l.Y, l.W*1.2);
			drawQuad(app, road, p.X, p.Y, p.W, l.X, l.Y, l.W);
		}

		draw objects
		for (int n = startPos + 300; n > startPos; n--)
			lines[n%N].drawSprite(app);

		app.display();
	}


	return 0;
}

结果图:(按住上键)

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值