Let's make 16 games in C++(十四):Tron

本文详细介绍了使用SFML和着色器技术创建一款增强版Tron游戏的过程,包括游戏背景设置、玩家控制逻辑、碰撞检测及光效实现。通过添加文字显示和动态光照效果,提升游戏体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、准备游戏需要的背景图片

//shader.frag
uniform vec2 frag_LightOrigin;	
uniform vec3 frag_LightColor; 	
uniform float frag_LightAttenuation;	
uniform vec2 frag_ScreenResolution; 
uniform sampler2D texture;
void main()
{		
    vec2 baseDistance =  gl_FragCoord.xy; 
    baseDistance.y = frag_ScreenResolution.y-baseDistance.y; 
    float d = length(frag_LightOrigin - baseDistance); 
    float a = 1.0/(frag_LightAttenuation * d);	
    vec4 color = vec4(a,a,a,1.0) * vec4(frag_LightColor, 1.0);  
    vec4 t = texture2D(texture, gl_TexCoord[0].xy);
    if (t[0]>color[0]) color[0]=t[0];
    if (t[1]>color[1]) color[1]=t[1];
    if (t[2]>color[2]) color[2]=t[2];
    gl_FragColor=color; 
}

 

2、绘制一个600x400的屏幕

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

using namespace sf;

const int W = 600;
const int H = 400;
int speed = 4;
bool field[W][H] = { 0 };

struct player
{
	int x;
	int y;
	int dir;
	Color color;
	player(Color c)
	{
		x = rand() % W;
		y = rand() % H;
		color = c;
		dir = rand() % 4;
	}
	void tick()
	{
		if (dir == 0)
		{
			y += 1;
		}
		if (dir == 1)
		{
			x -= 1;
		}
		if (dir == 2)
		{
			x += 1;
		}
		if (dir == 3)
		{
			y -= 1;
		}
	}

	Vector3f getColor()
	{
		return Vector3f(color.r, color.g, color.b);
	}

};


int main()
{
	srand(time(0));

	RenderWindow window(VideoMode(W, H), "The Tron Game!");
	window.setFramerateLimit(60);

	Texture texture;
	texture.loadFromFile("./Resources/images/background.jpg");

	Sprite sBackground(texture);
	player p1(Color::Red);
	player p2(Color::Green);

	Sprite sprite;
	RenderTexture t;
	t.create(W, H);
	t.setSmooth(true);
	sprite.setTexture(t.getTexture());
	t.clear();
	t.draw(sBackground);

	bool Game = 1;

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

		if (Keyboard::isKeyPressed(Keyboard::Left))
		{
			if (p1.dir != 2)
			{
				p1.dir = 1;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Right))
		{
			if (p1.dir != 1)
			{
				p1.dir = 2;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Up))
		{
			if (p1.dir != 0)
			{
				p1.dir = 3;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Down))
		{
			if (p1.dir != 3)
			{
				p1.dir = 0;
			}
		}

		if (Keyboard::isKeyPressed(Keyboard::A))
		{
			if (p2.dir != 2)
			{
				p2.dir = 1;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::D))
		{
			if (p2.dir != 1)
			{
				p2.dir = 2;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::W))
		{
			if (p2.dir != 0)
			{
				p2.dir = 3;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::S))
		{
			if (p2.dir != 3)
			{
				p2.dir = 0;
			}
		}


		if (!Game)
		{
			continue;
		}
		for (int i = 0; i < speed; i++)
		{
			p1.tick();
			p2.tick();
			if (field[p1.x][p1.y] == 1)
			{
				Game = 0;
			}
			if (field[p2.x][p2.y] == 1)
			{
				Game = 0;
			}
			field[p1.x][p1.y] = 1;
			field[p2.x][p2.y] = 1;

			CircleShape c(3);
			c.setPosition(p1.x, p2.y);
			c.setFillColor(p1.color);
			t.draw(c);
			c.setPosition(p2.x, p2.y);
			c.setFillColor(p2.color);
			t.draw(c);
			t.display();
		}

		//draw
		window.clear();
		window.draw(sprite);
		window.display();
	}


	return 0;
}

效果图:

3、添加文字:

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

using namespace sf;

const int W = 600;
const int H = 400;
int speed = 4;
bool field[W][H] = { 0 };

struct player
{
	int x;
	int y;
	int dir;
	Color color;
	player(Color c)
	{
		x = rand() % W;
		y = rand() % H;
		color = c;
		dir = rand() % 4;
	}
	void tick()
	{
		if (dir == 0)
		{
			y += 1;
		}
		if (dir == 1)
		{
			x -= 1;
		}
		if (dir == 2)
		{
			x += 1;
		}
		if (dir == 3)
		{
			y -= 1;
		}

		if (x >= W)
		{
			x = 0;
		}
		if (x < 0)
		{
			x = W - 1;
		}
		if (y >= H)
		{
			y = 0;
		}
		if (y < 0)
		{
			y = H - 1;
		}
	}

	Vector3f getColor()
	{
		return Vector3f(color.r, color.g, color.b);
	}

};


int main()
{
	srand(time(0));

	RenderWindow window(VideoMode(W, H), "The Tron Game!");
	window.setFramerateLimit(60);

	Texture texture;
	texture.loadFromFile("./Resources/images/background.jpg");

	Sprite sBackground(texture);
	player p1(Color::Red);
	player p2(Color::Green);

	Sprite sprite;
	RenderTexture t;
	t.create(W, H);
	t.setSmooth(true);
	sprite.setTexture(t.getTexture());
	t.clear();
	t.draw(sBackground);

	Font font;
	font.loadFromFile("./Resources/font/arial.ttf");
	Text text("YOU WIN!", font, 35);
	text.setPosition(W / 2 - 80, 20);

	bool Game = 1;

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

		if (Keyboard::isKeyPressed(Keyboard::Left))
		{
			if (p1.dir != 2)
			{
				p1.dir = 1;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Right))
		{
			if (p1.dir != 1)
			{
				p1.dir = 2;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Up))
		{
			if (p1.dir != 0)
			{
				p1.dir = 3;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Down))
		{
			if (p1.dir != 3)
			{
				p1.dir = 0;
			}
		}

		if (Keyboard::isKeyPressed(Keyboard::A))
		{
			if (p2.dir != 2)
			{
				p2.dir = 1;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::D))
		{
			if (p2.dir != 1)
			{
				p2.dir = 2;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::W))
		{
			if (p2.dir != 0)
			{
				p2.dir = 3;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::S))
		{
			if (p2.dir != 3)
			{
				p2.dir = 0;
			}
		}


		if (!Game)
		{
			window.draw(text);
			window.display();
			continue;
		}
		for (int i = 0; i < speed; i++)
		{
			p1.tick();
			p2.tick();
			if (field[p1.x][p1.y] == 1)
			{
				Game = 0;
				text.setColor(p2.color);
			}
			if (field[p2.x][p2.y] == 1)
			{
				Game = 0;
				text.setColor(p1.color);
			}
			field[p1.x][p1.y] = 1;
			field[p2.x][p2.y] = 1;

			CircleShape c(3);
			c.setPosition(p1.x, p2.y);
			c.setFillColor(p1.color);
			t.draw(c);
			c.setPosition(p2.x, p2.y);
			c.setFillColor(p2.color);
			t.draw(c);
			t.display();
		}

		//draw
		window.clear();
		window.draw(sprite);
		window.display();
	}


	return 0;
}

效果图:

4、添加着色器完善游戏逻辑

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

using namespace sf;

const int W = 600;
const int H = 400;
int speed = 4;
bool field[W][H] = { 0 };

struct player
{
	int x;
	int y;
	int dir;
	Color color;
	player(Color c)
	{
		x = rand() % W;
		y = rand() % H;
		color = c;
		dir = rand() % 4;
	}
	void tick()
	{
		if (dir == 0)
		{
			y += 1;
		}
		if (dir == 1)
		{
			x -= 1;
		}
		if (dir == 2)
		{
			x += 1;
		}
		if (dir == 3)
		{
			y -= 1;
		}

		if (x >= W)
		{
			x = 0;
		}
		if (x < 0)
		{
			x = W - 1;
		}
		if (y >= H)
		{
			y = 0;
		}
		if (y < 0)
		{
			y = H - 1;
		}
	}

	Vector3f getColor()
	{
		return Vector3f(color.r, color.g, color.b);
	}

};


int main()
{
	srand(time(0));

	RenderWindow window(VideoMode(W, H), "The Tron Game!");
	window.setFramerateLimit(60);

	Texture texture;
	texture.loadFromFile("./Resources/images/background.jpg");

	Sprite sBackground(texture);
	player p1(Color::Red);
	player p2(Color::Green);

	Sprite sprite;
	RenderTexture t;
	t.create(W, H);
	t.setSmooth(true);
	sprite.setTexture(t.getTexture());
	t.clear();
	t.draw(sBackground);

	Font font;
	font.loadFromFile("./Resources/font/arial.ttf");
	Text text("YOU WIN!", font, 35);
	text.setPosition(W / 2 - 80, 20);

	Shader *shader = new Shader;
	shader->loadFromFile("./Resources/files/shader.frag", Shader::Fragment);
	shader->setParameter("frag_ScreenResolution", Vector2f(W, H));
	shader->setParameter("frag_LightAttenuation", 100);
	RenderStates states;
	states.shader = shader;


	bool Game = 1;

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

		if (Keyboard::isKeyPressed(Keyboard::Left))
		{
			if (p1.dir != 2)
			{
				p1.dir = 1;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Right))
		{
			if (p1.dir != 1)
			{
				p1.dir = 2;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Up))
		{
			if (p1.dir != 0)
			{
				p1.dir = 3;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::Down))
		{
			if (p1.dir != 3)
			{
				p1.dir = 0;
			}
		}

		if (Keyboard::isKeyPressed(Keyboard::A))
		{
			if (p2.dir != 2)
			{
				p2.dir = 1;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::D))
		{
			if (p2.dir != 1)
			{
				p2.dir = 2;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::W))
		{
			if (p2.dir != 0)
			{
				p2.dir = 3;
			}
		}
		if (Keyboard::isKeyPressed(Keyboard::S))
		{
			if (p2.dir != 3)
			{
				p2.dir = 0;
			}
		}


		if (!Game)
		{
			window.draw(text);
			window.display();
			continue;
		}
		for (int i = 0; i < speed; i++)
		{
			p1.tick();
			p2.tick();
			if (field[p1.x][p1.y] == 1)
			{
				Game = 0;
				text.setColor(p2.color);
			}
			if (field[p2.x][p2.y] == 1)
			{
				Game = 0;
				text.setColor(p1.color);
			}
			field[p1.x][p1.y] = 1;
			field[p2.x][p2.y] = 1;


			t.display();

			shader->setParameter("frag_LightOrigin", Vector2f(p1.x, p1.y));
			shader->setParameter("frag_LightColor", p1.getColor());
			t.draw(sprite, states);
			shader->setParameter("frag_LightOrigin", Vector2f(p2.x, p2.y));
			shader->setParameter("frag_LightColor", p2.getColor());
			t.draw(sprite, states);
		}

		//draw
		window.clear();
		window.draw(sprite);
		window.display();
	}


	return 0;
}

结果图:

PS:如果出现关于setColor的错误:Project Properties > Configuration Properties > C/C++ > General > SDL checks选否

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值