插值原理
原理
color(x)=(x-x1)/(x2-x1)(color2-color1)+color1 x1<x<x2
假如说x伪3 那么color=(3-x1)/(x2-x1)(color2-color1)+color
可是图片纹理 这里不需要两种颜色,只需要获得碰撞点坐标后,如果是水平位置的墙,绿色方块,获取碰撞点x就是纹理的x坐标,也就是uv坐标中的u坐标,v坐标需要计算上面提到的差值,纹理是64X64像素,高度是64,。
这里先看下绘制投影墙是怎么做到的
center = 300h1 = 64 / dis * 277gao = h1 / 2kai = center - gaoen = center + h1
pygame.draw.line(screen, (55,40,140), (x + 100, kai), (x + 100, en))
计算每一列的高度后,定义从哪里是墙的中间点center,gao是一列的一半,加减gao计算每一列墙的起点与结束点这一列墙其实就是一条线,多条线绘制成投影墙。1起点是kai,结束点是en
碰撞点变量zx,zy
u=zx%64 这里%纹理宽度是为了不超出纹理大小
上面图片说明了我们只需要纹理的高度酒能正确映射纹理了,因为纹理横坐标就是碰撞点x坐标%纹理宽度,v需要计算差值color(x)=(x-x1)/(x2-x1)(color2-color1)+color1 x1<x<x2
先开始一个循环,遍历每一列投影墙的y坐标,oy,然后根据差值用当前点oy减去起点kai/结束点en-kai后乘上纹理高度64,原公式(x-x1)/(x2-x1)(color2-color1)+color1是为了在两种颜色进行渐变,在这里不需要两种颜色,只要知道纹理纵坐标y或者v的起始点与结束点就能差值这一列纹理的颜色
for oy in range(int(kai),int(en)):v=(oy-kai)/(en-kai)*64u=zx%64#print(v,oy,en-kai,int(v)%64,ix)#print(zx, zy,cx,cy)#tex_x = int(test_x % 1 * tex_width) # 使用固定纹理宽度来映射screen.set_at((x, oy), img.get_at((int(u), int(v)%64)))
import pygame
from pygame.locals import *
import sys
import mathpygame.init()width, height = 900, 600
screen = pygame.display.set_mode((width, height))
c=pygame.time.Clock()
q = [[1, 1, 1,1, 1, 1, 1, 1],#0 x坐标[1, 0, 0, 0, 0, 0, 0, 1],#1x坐标[1, 0, 0, 0, 0, 0, 0, 1],#2x坐标[1, 0, 0, 0, 0, 0, 0, 1],#3x坐标[1, 0, 0, 0, 0, 0, 0, 1],#4x坐标[1, 0, 0, 0, 0, 1, 0, 1],#5x坐标[1, 0, 0, 0, 0, 0, 0, 1],[1, 0, 0, 0, 0, 0, 0, 1],[1, 0, 0, 0, 0, 0, 0, 1],[1, 0, 0, 0, 0, 0, 0, 1],[1, 0, 0, 0, 0, 0, 0, 1],#上 下[1, 0, 0, 0, 0, 0, 0, 1],[1,1, 1, 1, 1, 1, 1, 1]#右]px=180
py=270
du=0
left=False
right=False
down=False
up=False
img = pygame.image.load("4.png") # 替换为您自己的图像文件路径
img=pygame.transform.scale(img,(30,30))xuanzhuanjiao=70
img=pygame.image.load("1.png").convert_alpha()
def player(x,y,zhuan):#pygame.draw.line(screen, (40, 140, 40), (x, y), (74, 713))#print(du)screen.blit(zhuan,(x,y))
while True:screen.fill((255, 255, 255))x = 0#c.tick(70)for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()keys = pygame.key.get_pressed()if keys[pygame.K_UP]:#print("up")py=py -10if keys[pygame.K_LEFT]:#zuopx=px-1if keys[pygame.K_DOWN]:#xia#print("up")py = py + 10print(q[int(px//60)][int(py//60)],"0控 1强 角色格子",int(px//60),int(py//60))if keys[pygame.K_RIGHT]:#you#xuanzhuanjiao=xuanzhuanjiao+1px=px+1#print(q[int(px // 60)][int(py // 60)], "0控 1强 角色格子", int(px // 60), int(py // 60))#print(sz)#在这直接写会变成子弹,写成函数qiang(ci)就能画成一次,不会移动的墙if keys[pygame.K_a]:xuanzhuanjiao=xuanzhuanjiao+1right=Trueif event.type == pygame.KEYUP:right = Falseif keys[pygame.K_l]:xuanzhuanjiao=xuanzhuanjiao-10#if keys[pygame.K_SPACE]:for h in range(len(q)):#画墙#print(q[h],"行",h)for g in range(len(q[h])):if q[h][g]==1:#print(q[h][g],"个",g,h)pz=pygame.draw.rect(screen, (140, 240, 40), (0+h*60, 0+g*60, 60, 60))screen.blit(img, (180, 0))#qsz.append(pz)#player(px, py, img)for x in range(190):dis=0while True:angle= xuanzhuanjiao - 30 + (x / width) * 60dis=dis+0.1#self.x = dis + math.cos(math.radians(self.xuanzhuanjiao)) * 90#self.y = dis - math.sin(math.radians(self.xuanzhuanjiao)) * 90zx=px+math.cos(math.radians(angle)) * diszy=py - math.sin(math.radians(angle)) * dis#print(dis)#if zx//60<13 and zy//60<7:if q[int(zx//60)][int(zy//60)]==1 :#子弹超出没有强后会显示错误 超出墙索引max_wall_height = height # 设置墙的最大高度为屏幕高度的2/3# 计算墙的高度,并确保不超过最大墙高wall_height = min(height / dis, max_wall_height)ceiling = (height - wall_height) // 2floor = height - ceilingtex_width = img.get_width() # 纹理宽度不变#tex_x = int(test_x % 1 * tex_width) # 使用固定纹理宽度来映射#pygame.draw.line(screen, (140, 40, 40), (x, int(ceiling)*1), (x, int(floor)*1))center = 300h1 = 64 / dis * 277gao = h1 / 2kai = center - gaoen = center + h1pygame.draw.line(screen, (40, 40, 40), (px, py),(zx ,zy))#ix = int(zx % 1 * 64)0#iy = int(300 + gao) % 64cx=zx-math.floor(zx)cy=zy-math.floor(zy)ix = int(zx)%64iy = int(cy*64)%64u=zx#print(kai-en,en,kai)#print(zx,zy)#print(zx % 64, int(zx % 64)%255)#print(zx, zy, zx % 60, x, int(u * 10) % 255)#tex_x = int(zx % 1 * tex_width) # 使用固定纹理宽度来映射#pygame.draw.line(screen, (int(zx%64)%255,40,140), (x + 100, kai), (x + 100, en))tex_x = int(zx % 64) # 使用固定纹理宽度来映射# for y in range(int(ceiling), int(floor)):# tex_y = int((y - ceiling) / (floor - ceiling) * img.get_height())# if 0 <= tex_x < img.get_width() and 0 <= tex_y < img.get_height():# screen.set_at((x, y*2), img.get_at((tex_x, tex_y)))for oy in range(int(kai),int(en)):v=(oy-kai)/(en-kai)*64u=cx#print(v,oy,en-kai,int(v)%64,ix)#print(zx, zy,cx,cy)#tex_x = int(test_x % 1 * tex_width) # 使用固定纹理宽度来映射#pygame.draw.line(screen, (img.get_at((int(ix)%64,int(v)%64))), (x+100,kai), (x+100, en))screen.set_at((x, oy), img.get_at((ix, int(v)%64)))#print(ix,v)#print(dis)breakpygame.display.flip()