opengl画旋转的正方形_错觉图片生成实验 - 正方形错觉

e2044bbf243014fc18e9e45225e4e211.png

(图书介绍:童晶:《C和C++游戏趣味编程》新书预告)

这学期的线下C语言课程,大一同学们学完旋转蛇案例后(童晶:第4章 旋转蛇(《C和C++游戏趣味编程》配套教学视频)),布置了一次错觉图片生成实验的PBL,给了大家5天时间分组完成代码、ppt报告。

这次,介绍王翌骏、陈凯、马学强同学实现的正方形错觉。由于同学们学习C语言刚一个月,还没有正式学习数组、函数等语法知识,因此代码可能不够完善。以下提供了分步骤的实现思路、代码,大家可以参考。

首先是同学们调研的目标效果:

7dec3a9b504f67a305677efd5b319b64.png

斜向方块的边看起来是弧线,实际上是直线,受黑白条纹影响产生是弧线边的错觉。

STEP 1:划出线

●利用函数在不同两点间划出直线

●代码行数(不算变量的定义)10

●难度:较简单

●PS:其实这线画出来对于最后的效果没有影响,但可以用来作为判断第二步骤的标准

8ca0efcf0030678028d97f79c24b29e5.png

STEP 2:画出大背景

●利用solidrectangle以及判断和循环来做出

●代码行数:约70行

●难度:一般,但是繁琐,需要大量的循环判断。

cc209c05a908296623d9c4114d2c385a.png

STEP 3:挖空中间部分

●利用clearpolygon函数进行清除

●代码行数:约十行

●难度:简单(简单的循环,但是所用到新的函数以及数据类型POINT,通过easy_x查询)

4ff6a22592105e756477ac5697aa1663.png

STEP 4:画出中间部分

●利用坐标,想逃循环判断画出中间部分的

●代码行数:约45行

●难度:困难(尝试多次未果,因为直接用函数确定范围会十分复杂,但我在easyx上看到了setorigin函数用来定义原点,这样在菱形中的函数是一样的,省去了很多麻烦 )

1d573d34d4d1560a78446b7f08cc5261.png

STEP5:结合

将第四步和第三步结合,便得到了错觉图形

1c735705a1777dcfa9c076b666a2dfac.png
#include<stdio.h>
#include<graphics.h>
#include<conio.h>

int main()
{  
	int site_x, site_y;
	int screen_x, screen_y;
	int length = 160;
	int width = 8;
	int left,top;
	int count1, count2;
	int x = 1, y = 1, t = 1,k;
	screen_x = 640, screen_y = 640;
	initgraph(screen_x, screen_y);
	cleardevice();
	for (t;t < 8;t++)//输出直线
	{
		if (t <= 4)
		{
			line(0, 160 * t - 80, 160 * t - 80, 0);
			line(0, 160 * t - 80, 720 - 160*t , 640);
			line(720 - 160 * t, 640, 640, 720 - 160 * t);
			line(640, 720 - 160 * t, 160 * t - 80, 0);		
		}
	}
	
	for (y = 1;y <= 4;y++)
	{
		for (x=1;x <= 40;x++)
		{
			if (y % 2 != 0)
			{
				if (x <= 10)//第一个方块以及向下平移
				{
					left = 16 * x - 8;
					top = length * (y - 1);
					
					fillrectangle(left, top, left + width, top+length);
				}
				if (x > 10 && x <= 20)//第二个
				{
					left = 160;
					top = 16 * (x - 11)+ length * (y - 1);
					fillrectangle(left, top, left + length, top + width);
				}
				if (x <= 30 && x > 20)//第三个
				{
					left = 16 * x - 16;
					top = top = length * (y - 1);
					fillrectangle(left, top, left + width, top+length);
				}
				if (x > 30)//第四个
				{
					left = 480;
					top = 16 * (x - 31)+8 + length * (y - 1);
					fillrectangle(left, top, left + length, top + width);
				}
			}
			else
			{
				if(x<=10)
				{
					left = 0;
					top = length * (y - 1) + 8+16*(x-1);
					fillrectangle(left,top,left+length,top+width);
				}
				if(x > 10 && x <= 20)
				{
					left = 160 +16* (x - 11);
					top=length*(y-1);
					fillrectangle(left, top, left + width, top + length);
				}
				if(x <= 30 && x > 20)
				{
					top = length * (y - 1)  + 16 * (x - 21);
					left = 320;
					fillrectangle(left, top, left + length, top + width);;
				}
				if(x > 30)
				{
					top = length*(y-1);
					left = 480 + 8 + 16 * (x - 31);
					fillrectangle(left, top, left + width, top + length); ;
				}
			}

		}
	}
	int r = 80;//清除中间部分
	for (x = 80; x <= 560; x = x + 160)
	{
		for (y = 80; y <= 560; y = y + 160)
		{

			POINT pts[] = { {x, y - r}, {x - r,y}, {x, y + r},{x + r,y} };
			clearpolygon(pts, 4);
		}
	}
	for (count1 = 1;count1 <= 4;count1++)//重新绘制内部图形
	{
		for (count2 = 1;count2 <= 4;count2++)
		{
			setorigin(80 + 160 * (count1 - 1), 80 + 160 * (count2 - 1));
			for (x = -80;x <= 80;x++)
			{
				for (y = -80; y <= 80;y++)
				{
					for (k = 1;k <= 10;k++)
					{
						if ((x + y <= 80) && (x + y >= -80) && (y - x <= 80) && (y - x >= -80))
						{
							if ((count1 + count2) % 2 == 0)
							{
								if (count1 == 1 || count1 == 4)
									if (x > -80 + 16 * (k - 1) && x <= 16 * (k - 1) - 72)
										putpixel(x, y, WHITE);
									else
										;
								else if (count1 == 2 || count1 == 3)
									if (x > -72 + 16 * (k - 1) && x <= 16 * (k - 1) - 64)
										putpixel(x, y, WHITE);

							}
							else
							{
								if (count1 == 1 || count1 == 4)
									if (y >= -80 + 16 * (k - 1) && y <= 16 * (k - 1) - 72)
										putpixel(x, y, WHITE);
									else
										;
								if (count1 == 2 || count1 == 3)
									if (y >= -72 + 16 * (k - 1) && y <= 16 * (k - 1) - 64)
										putpixel(x, y, WHITE);
							}

						}
					}
				}
			}
		}
	}
	_getch();
	return 0;
}

感想

1:分步骤逐一解决,有目的性地去写代码是不二法门

2:看起来很难完成的步骤,需要查找相关的资料以及运用一些数学思维

3:团队协作统筹很重要

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值