cjjJasonchen 发表于 2024-8-28 17:36:07

当你将堆叠法伪3d运用到实操当中。。。。

本帖最后由 cjjJasonchen 于 2024-8-28 17:38 编辑





俯仰正负90度(后续可能改成360度全向),绕X轴旋转360度

通过pygame的get_at和set_at函数,设置史莱姆的表情

"""
俯视视角下的伪3D实现测试(切片堆叠法
"""

import pygame
import sys, pickle
from typing import List
from pygame.locals import *


class Sprites3D:
    X, Y, Z = 0, 1, 2

    def __init__(
            self,
            images: [],# 图像列表 从上到下
            angle: [],# 角度列表 图片中心为中心,俯仰角度
            position: [],# 位置 x, y
    ):
      self.images = images
      self.angle = angle
      self.rect = self.images[-1].get_rect()
      self.rect.center = position
      self.height = len(self.images)

    def set_face(self, image, width=15):
      """设置表情,接受一张高度、宽度与自身相同的图片"""
      rect = image.get_rect()
      images = self.images
      range_x = range(rect)
      range_w = range(87,95)
      for index in range(len(images)):# 被替换的图片的索引
            for x in range_x:# 表情的x轴位置
                for width in range_w:
                  images.set_at((x, width), image.get_at((x, index)))



    def update(self):
      pass

    def draw(self, screen):
      h = self.height
      angle = self.angle
      shift = 0# 每张图片向上的偏移量
      for index in range(h-1, -1, -1):
            image = self.images
            image = pygame.transform.rotate(image, angle)

            # 俯仰
            if -45 <= angle <= 45:
                shift += (angle / 45) * 0.75
            elif -90 <= angle < -45:
                shift += ((angle + 45) / 45) * 0.25 - 0.75
            elif 45 < angle <= 90:
                shift += ((angle - 45) / 45) * 0.25 + 0.75

            rect = image.get_rect()
            image = pygame.transform.smoothscale(image,, rect * (1 - abs(angle / 90))])
            rect = image.get_rect()
            rect.center = self.rect.centerx, self.rect.centery
            rect.y += shift

            screen.blit(image, rect)



# 颜色常量
WHITE = (255,255,255)
BLACK = (0,0,0)


size = width, height = 800,600

screen = pygame.display.set_mode(size)

pygame.display.set_caption("title")

clock = pygame.time.Clock()

delay = 60 # 延时计时器(1秒)

# 是否全屏
fullscreen = False
screen_change = False

# 背景颜色设定
bg_color = WHITE

running = True

# 伪3d对象
image_list = []
for i in range(12):
    image_list.append(pygame.image.load("images/top.png"))
for i in range(75):
    image_list.append(pygame.image.load("images/center.png"))
for i in range(13):
    image_list.append(pygame.image.load("images/top.png"))
s3d = Sprites3D(image_list,,)
s3d.set_face(pygame.image.load("images/face1.png"))

while running:

    # 设定帧数
    clock.tick(60)

    # 延时计时器刷新
    if delay == 0:
      delay = 60

    delay -= 1

    # 检测是否全屏
    if fullscreen and screen_change:
      screen = pygame.display.set_mode(size,FULLSCREEN,HWSURFACE)
      screen_change = False
    elif screen_change:
      screen = pygame.display.set_mode(size)
      screen_change = False

    # 事件检测
    for event in pygame.event.get():
      if event.type == QUIT:
            pygame.quit()
            sys.exit()

      # 鼠标
      if event.type == MOUSEBUTTONDOWN:
            print(1)
            

      # 按键按下事件
      if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
               
            #F11切换全屏
            if event.key == K_F11:
                fullscreen = not fullscreen
                screen_change = True

            if event.key == K_UP:
                print("up1")
                if s3d.angle > -85:
                   s3d.angle -= 5
                   print("up2")
                  
            elif event.key == K_DOWN:
                if s3d.angle < 85:
                   s3d.angle += 5

            elif event.key == K_LEFT:
                   s3d.angle -= 5

            elif event.key == K_RIGHT:
                   s3d.angle += 5

            elif event.key == K_1:
                s3d.set_face(pygame.image.load("images/face1.png"))

            elif event.key == K_2:
                s3d.set_face(pygame.image.load("images/face2.png"))

            elif event.key == K_3:
                s3d.set_face(pygame.image.load("images/face3.png"))

      # 按键抬起事件
      if event.type == KEYUP:
            pass

    #画背景
    screen.fill(bg_color)

    # 刷新xxx
    s3d.update()

    #画 xxxx
    s3d.draw(screen)
   
    # 刷新界面
    pygame.display.update()





按键:

1:方眼睛方嘴巴
2:委屈脸
3:笑脸
上:抬头
下:低头
左:左旋转
右:右旋转

素材:



注意:这个帖子会持续更新,欢迎大家借鉴,后续会将这个角色作为我下一个游戏实操项目的主角

求评分啦~




FishC 发表于 2024-8-28 17:37:01

堆叠法伪3D是一种通过在2D平面上堆叠多个图层来模拟3D效果的技术。以下是如何将堆叠法伪3D运用到实际项目中的简要步骤:

1. **准备图层**:将每个图层的图像准备好,这些图像将代表不同的深度。

2. **设置图层位置**:根据每个图层的深度,设置它们在2D平面上的位置。通常,较远的图层会放置在较低的位置。

3. **调整透明度**:为了增强3D效果,可以调整每个图层的透明度,使得较远的图层更加透明。

4. **添加交互**:如果需要交互效果,可以通过鼠标或触摸事件来改变图层的位置或透明度,从而模拟视角的变化。

以下是一个简单的HTML和CSS示例,展示了如何使用堆叠法伪3D效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Stacked Pseudo 3D</title>
    <style>
      .layer {
            position: absolute;
            width: 100%;
            height: 100%;
            background-size: cover;
      }
      .layer1 { background-image: url('layer1.png'); z-index: 1; opacity: 0.9; }
      .layer2 { background-image: url('layer2.png'); z-index: 2; opacity: 0.7; }
      .layer3 { background-image: url('layer3.png'); z-index: 3; opacity: 0.5; }
    </style>
</head>
<body>
    <div class="layer layer1"></div>
    <div class="layer layer2"></div>
    <div class="layer layer3"></div>
</body>
</html>

这个示例中,我们使用了三个图层,每个图层都有不同的透明度和z-index,以模拟深度效果。你可以根据需要调整图层的数量、位置和透明度,以实现更复杂的3D效果。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

不二如是 发表于 2024-8-28 20:45:15

有意思!

python爱好者. 发表于 2024-8-31 22:12:21

可爱的史莱姆)
开学咯,最近我好久没来论坛了,忙着预习哇...

python爱好者. 发表于 2024-8-31 22:12:57

期待真3d(bushi

cjjJasonchen 发表于 2024-9-1 09:49:03

python爱好者. 发表于 2024-8-31 22:12
期待真3d(bushi

真3d试过了,感觉只用pygame的画太麻烦了,长方体的八个顶点还比较好算,但是把图片渲染到长方体上非常困难{:10_262:}

可能还是需要使用opengl。
页: [1]
查看完整版本: 当你将堆叠法伪3d运用到实操当中。。。。